Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 如何使用马达';使用FastAPI'开放下载流工作;那是什么?_Mongodb_Fastapi_Mongodb Motor - Fatal编程技术网

Mongodb 如何使用马达';使用FastAPI'开放下载流工作;那是什么?

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

我正在构建一个FastAPI端点,web客户机用户可以在这里下载作为GridFS块存储在MongoDB中的文件。然而,FastAPI并不接受motor方法返回的所谓类似文件的对象

我已经有了一个端点,它可以以某种形式获取文件,并将它们上传到MongoDB。我希望类似的下载助手功能可以像这样简单:

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