Mongodb 如何使用马达';使用FastAPI'开放下载流工作;那是什么?
我正在构建一个FastAPI端点,web客户机用户可以在这里下载作为GridFS块存储在MongoDB中的文件。然而,FastAPI并不接受motor方法返回的所谓类似文件的对象 我已经有了一个端点,它可以以某种形式获取文件,并将它们上传到MongoDB。我希望类似的下载助手功能可以像这样简单:Mongodb 如何使用马达';使用FastAPI'开放下载流工作;那是什么?,mongodb,fastapi,mongodb-motor,Mongodb,Fastapi,Mongodb Motor,我正在构建一个FastAPI端点,web客户机用户可以在这里下载作为GridFS块存储在MongoDB中的文件。然而,FastAPI并不接受motor方法返回的所谓类似文件的对象 我已经有了一个端点,它可以以某种形式获取文件,并将它们上传到MongoDB。我希望类似的下载助手功能可以像这样简单: async def upload_file(db, file: UploadFile): """ Uploads file to MongoDB GridFS fi
async def upload_file(db, file: UploadFile):
""" Uploads file to MongoDB GridFS file system and returns ID to be stored with collection document """
fs = AsyncIOMotorGridFSBucket(db)
file_id = await fs.upload_from_stream(
file.filename,
file.file,
# chunk_size_bytes=255*1024*1024, #default 255kB
metadata={"contentType": file.content_type})
return file_id
我的第一次尝试是使用以下帮助器:
async def download_file(db, file_id):
"""Returns AsyncIOMotorGridOut (non-iterable file-like object)"""
fs = AsyncIOMotorGridFSBucket(db)
stream = await fs.open_download_stream(file_id)
# return download_streamer(stream)
return stream
app.get("/file/{file_id}")
async def get_file(file_id):
file = await download_file(db, file_id)
return StreamingResponse(file, media_type=file.content_type)
我的FastAPI端点如下所示:
async def download_file(db, file_id):
"""Returns AsyncIOMotorGridOut (non-iterable file-like object)"""
fs = AsyncIOMotorGridFSBucket(db)
stream = await fs.open_download_stream(file_id)
# return download_streamer(stream)
return stream
app.get("/file/{file_id}")
async def get_file(file_id):
file = await download_file(db, file_id)
return StreamingResponse(file, media_type=file.content_type)
尝试下载具有有效文件id的文件时,出现以下错误:TypeError:'AsyncIOMotorGridOut'对象不是迭代器
我的第二次尝试是创建一个生成器来迭代文件块:
async def download_streamer(file: AsyncIOMotorGridOut):
""" Returns generator file-like object to be served by StreamingResponse
https://fastapi.tiangolo.com/advanced/custom-response/#streamingresponse
"""
chunk_size = 255*1024*1024
for chunk in await file.readchunk():
print(f"chunk: {chunk}")
yield chunk
然后我在我的下载文件助手中使用注释的返回下载流(stream)
,但由于某些原因,每个块都只是255
的整数
使用motor从MongoDB中获取文件并将其作为FastAPI web响应流式传输而不使用临时文件的最佳方法是什么?(我没有访问硬盘的权限,也不想将整个文件存储在内存中——我只想通过FastAPI将文件从MongoDB流式传输到客户端,一次一块)。我的解决方案是创建一个生成器,它恰好是Python 3.6+语法的。这样的迭代器使用FastAPI的StreamingResponse的异步变体,并使用方法()一次读取一个GridFS块。当使用upload\u from\u stream()
将文件存储在MongoDB中时,会设置此区块大小。可选的实现是使用.read(n)
一次读取n
字节。我选择使用readchunk()
,这样在流期间一次只提取1个DB文档(每个GridFS文件被分成块,并在DB中一次存储一个块)
未来的改进是让download_file()
返回一个元组,以便不仅包括生成器,还包括元数据,如ContentType