python 如何使用FastAPI从内存缓冲区返回PDF文件?

j2datikz  于 2023-06-20  发布在  Python
关注(0)|答案(2)|浏览(317)

我想从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文件作为响应。

ymdaylpp

ymdaylpp1#

由于整个文件数据已经加载到内存中,因此没有使用StreamingResponse的实际原因。您应该改为使用Response,通过传递文件字节(使用BytesIO.getvalue()获取包含缓冲区全部内容的字节),定义media_type,以及设置Content-Disposition头,以便PDF文件可以在浏览器中查看或下载到用户的设备。有关更多详细信息和示例,请查看this answer以及thisthis。相关答案也可以在here中找到。
此外,由于调用close()方法时会丢弃buffer,因此您也可以使用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()  # BytesIO stream containing the pdf data
    # ...
    background_tasks.add_task(buffer.close)
    headers = {'Content-Disposition': 'inline; filename="out.pdf"'}
    return Response(buffer.getvalue(), headers=headers, media_type='application/pdf')

要下载PDF文件而不是在borwser中查看,请用途:

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

bmvo0sr52#

我的缓冲区和代码发送pdf作为一个可下载的链接在http://127.0.0.1:8000/docs添加在标题字典“content-type”:“application/octet-stream”

async def convert_img_to_webp(img):
    image_io = BytesIO()
    image = Image.open(img)
    image.convert("RGB")
    image.save(image_io,"PDF")
    image_io.seek(0)
    # BackgroundTasks.add_task(image_io.close)
    return image_io

@router.post("/image/")
async def upload_file(file:UploadFile):
    if file:
        data = await convert_img_to_webp(file.file)
        headers = {'Content-Disposition': 'inline; filename="sample.pdf"',"content-type": "application/octet-stream"}
        return StreamingResponse(data,media_type='application/pdf',headers=headers)
    else:
        print("file not found")
        return

相关问题