You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PyMuPDF处理PDF返回前端时遇UnicodeDecodeError求助

解决PyMuPDF处理PDF返回前端时的UnicodeDecodeError问题

问题场景

我尝试用PyMuPDF打开上传的PDF文件,编辑后返回前端,代码如下:

@app.post('/return_pdf')
async def return_pdf(uploaded_pdf: UploadFile):
    print("Filetype: ", type(uploaded_pdf)) # <class 'starlette.datastructures.UploadFile'>
    document =  fitz.open(stream=BytesIO(uploaded_pdf.file.read()))
    for page in document:
        for area in page.get_text('blocks'):
            box = fitz.Rect(area[:4])
            if not box.is_empty:
                page.add_rect_annot(box)
    
    return {'file': document.tobytes()}

遇到的错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x9c in position 702: invalid start byte

补充尝试:

  • 读取文件时,仅BytesIO(uploaded_pdf.file.read())能被PyMuPDF接受
  • 尝试直接返回文件而非转字节,出现类似错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc7 in position 10: invalid continuation byte
  • 尝试给fitz.open()传入编码参数,但该方法不支持此参数

解决方案

1. 正确读取上传文件的二进制内容

UploadFile的file对象是原生文件句柄,直接read()可能存在指针位置问题,建议先重置指针再读取:

uploaded_pdf.file.seek(0)  # 将文件指针重置到开头
pdf_bytes = uploaded_pdf.file.read()
document = fitz.open(stream=BytesIO(pdf_bytes))

2. 用二进制响应替代JSON返回

FastAPI/Starlette返回JSON时会自动尝试将字节内容解码为UTF-8,引发错误。应直接返回Response对象并指定正确的媒体类型:

from fastapi import Response

@app.post('/return_pdf')
async def return_pdf(uploaded_pdf: UploadFile):
    uploaded_pdf.file.seek(0)
    pdf_bytes = uploaded_pdf.file.read()
    document = fitz.open(stream=BytesIO(pdf_bytes))
    
    for page in document:
        for area in page.get_text('blocks'):
            box = fitz.Rect(area[:4])
            if not box.is_empty:
                page.add_rect_annot(box)
    
    modified_pdf_bytes = document.tobytes()
    return Response(content=modified_pdf_bytes, media_type="application/pdf")

3. 显式关闭文档(可选)

虽然PyMuPDF会自动处理资源,显式关闭文档可避免潜在的资源泄漏:

document.close()

内容的提问来源于stack exchange,提问作者Manuel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:12:16