【问题标题】:How to return a PDF file from in-memory buffer using FastAPI?如何使用 FastAPI 从内存缓冲区返回 PDF 文件?
【发布时间】:2022-09-24 22:19:55
【问题描述】:

我想从 s3 获取一个 PDF 文件,然后从 FastAPI 后端返回到前端。

这是我的代码:

@router.post(\"/pdf_document\")
def get_pdf(document : PDFRequest) :
    s3 = boto3.client(\'s3\')
    file=document.name
    f=io.BytesIO()
    s3.download_fileobj(\'adm2yearsdatapdf\', file,f)
    return StreamingResponse(f, media_type=\"application/pdf\")

此 API 返回200 状态码,但不返回 PDF 文件作为响应。

    标签: python amazon-s3 boto3 fastapi


    【解决方案1】:

    由于整个文件数据已经加载到内存中,因此您不应该使用StreamingResponse。您应该使用Response,通过传递文件字节(使用BytesIO.getvalue() 来获取包含缓冲区全部内容的字节),定义media_type,以及设置Content-Disposition 标头,以便PDF 文件既可以在浏览器中查看,也可以下载到用户的设备中。有关更多详细信息,请查看this,以及thisthis 答案。另外,作为buffer is discarded when the close()method is called,你也可以使用FastAPI/Starlette的BackgroundTasks在返回响应后关闭buffer,以释放内存。或者,您可以使用pdf_bytes = buffer.getvalue() 获取字节,然后使用buffer.close() 关闭缓冲区,最后使用return Response(pdf_bytes, headers=...。例子:

    from fastapi import Response, BackgroundTasks
    
    @app.get("/pdf")
    def get_pdf(background_tasks: BackgroundTasks):
        buffer = io.BytesIO()
        # ...
        background_tasks.add_task(buffer.close)
        headers = {'Content-Disposition': 'inline; filename="out.pdf"'}
        return Response(buffer.getvalue(), headers=headers, media_type='application/pdf')
    

    要下载 PDF 文件而不是在浏览器中查看,请使用:

    headers = {'Content-Disposition': 'attachment; filename="out.pdf"'}
    

    【讨论】:

    • 用本地文件测试我得到 AttributeError: '_io.BytesIO' object has no attribute 'encode' 错误
    • 那应该是buffer.getvalue() 来获取包含缓冲区全部内容的字节。
    猜你喜欢
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 2013-08-29
    • 2021-09-03
    • 1970-01-01
    相关资源
    最近更新 更多