python - 如何从 FastAPI 中的 UploadFile 获取文件路径?
问题描述
基本上,我正在尝试创建一个端点以将文件上传到 S3
async def upload_files(filepath: str, upload_file_list: List[UploadFile] = File(...)):
for upload_file in upload_file_list:
abs_file_path = "/manual/path/works" + upload_file.path
# Replace above line to get absolute file path from UploadFile
response = s3_client.upload_file(abs_file_path,bucket_name,
os.path.join(dest_path, upload_file.filename))
以上是我将多个文件上传到 S3 存储桶的代码。
s3_client.upload_file()
接受要上传的文件的绝对文件路径。当我手动放置完整路径时它正在工作。
这没有用:
response = s3_client.upload_file(upload_file.filename, bucket_name,
os.path.join(dest_path, upload_file.filename))
有没有办法让这个绝对路径进入FastAPI
?temp_path
或者没有复制或写入文件的任何替代方案?
如果没有,那么使用任何替代方法boto3
将文件上传到 S3FastAPI
解决方案
UploadFile 使用 Python 的SpooledTemporaryFile,它是“存储在内存中的文件”,并且“一关闭就销毁”。您可以读取文件内容(i.e., contents = await file.read())
,然后将这些字节上传到您的服务器(如果允许),或者将上传文件的内容复制到NamedTemporaryFile中,如此处所述。与 SpooledTemporaryFile 不同,NamedTemporaryFile “保证在文件系统中有一个可见的名称”,即“可以用来打开文件”。临时文件的路径可以通过file_copy.name
contents = await file.read()
file_copy = NamedTemporaryFile('wb', delete=False)
f = None
try:
# Write the contents to the temp file
with file_copy as f:
f.write(contents);
# Here, upload the file to your S3 service
f = open(file_copy.name, 'rb')
print(f.read(10))
finally:
if f is not None:
f.close() # Remember to close the file
os.unlink(file_copy.name) # delete the file
更新
此外,可以使用该file
属性访问实际的 Python 文件。根据文档:
file
: 一个SpooledTemporaryFile(一个类似文件的对象)。这是您可以直接传递给需要“类文件”对象的其他函数或库的实际 Python 文件。
因此,您也可以尝试使用upload_fileobj
函数并传递upload_file.file
:
response = s3_client.upload_fileobj(upload_file.file, bucket_name, os.path.join(dest_path, upload_file.filename))
或者,使用 SpooledTemporaryFile 的属性传递一个类似文件的对象,该属性_file
返回一个io.BytesIO或io.TextIOWrapper对象(取决于是否指定了二进制或文本模式)。
response = s3_client.upload_fileobj(upload_file.file._file, bucket_name, os.path.join(dest_path, upload_file.filename))
更新 2
您甚至可以将字节保存在内存缓冲区BytesIO中,使用它将内容上传到 S3 存储桶,最后关闭它(“调用该close()
方法时会丢弃缓冲区。”)。请记住在完成对 BytesIO 流的写入后调用seek(0)
方法将光标重置回文件的开头。
contents = await file.read()
temp_file = io.BytesIO()
temp_file.write(contents)
temp_file.seek(0)
s3_client.upload_fileobj(temp_file, bucket_name, os.path.join(dest_path, upload_file.filename))
temp_file.close()
推荐阅读
- firebase - 使用 @firebase/testing 连接到 Firestore 模拟器
- node.js - 使用 node js api 时如何从 React js 前端应用程序中使用 windows
- javascript - puppeteer request.continue 无法使用覆盖的标头主机
- php - 如何在php上的服务器端数据表脚本上使用三元条件处理空值?
- sql - 来自 sqlzoo.net 的嵌套选择测验的 Q5
- xml - 在 Yocto 中找不到 fop 命令的依赖项
- java - 如何以 2019-12-29 05:59:59.9999990 +00:00 的格式将一天结束作为 OffsetDateTime?
- apache-kafka - 连接拒绝模式注册表
- wordpress - 本地主机上的 WordPress 永久链接问题
- android - Display.HdrCapabilities 和 configuration.isScreenHdr 有什么区别