使用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
相关产品推荐
相关产品推荐

