根本原因是fitz.page.get_pixmap()返回的原始像素数据未经图像格式编码,直接转bytes后缺乏png/jpeg文件头,导致浏览器无法解析;必须用pil中转并显式保存为标准图像格式。

PyMuPDF生成PDF页面图片时,为什么Flask返回空白或400错误
根本原因通常是 fitz.Page.get_pixmap() 返回的像素图未正确转为可HTTP传输的格式,且常见于忽略色彩空间、DPI或直接用 bytes() 导出原始数据。Flask的 Response 要求内容是 bytes 或可迭代的 bytes,而 PyMuPDF 的 Pixmap.tobytes() 默认输出的是原始 RGB/BGR 数据(无文件头),浏览器无法识别。
必须显式指定图像格式(如 "png")并用 PIL.Image 中转编码,否则返回的二进制流不是合法 PNG/JPEG 文件:
from PIL import Image
import io
<p>pix = page.get_pixmap(dpi=120) # 显式设 dpi,避免默认 72 太模糊
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
buf = io.BytesIO()
img.save(buf, format="PNG")
buf.seek(0)
return Response(buf.getvalue(), mimetype="image/png")</p>
如何安全加载用户上传的PDF而不崩溃
PyMuPDF 对损坏、加密或超大PDF非常敏感,fitz.open() 可能抛出 fitz.FileDataError、fitz.EmptyFileError 或直接卡死。不能直接把 request.files["pdf"].read() 塞给 fitz.open() —— 它不接受 bytes-like 对象(除非明确传入 stream=True)。
- 用
io.BytesIO(request.files["pdf"].read())构造流,再传给fitz.open(stream=...) - 始终用
try/except捕获fitz.FileDataError和RuntimeError(后者常因内存不足或加密PDF触发) - 限制 PDF 页数和总大小:比如只允许前 50 页,且文件体积 ≤ 20MB(Flask 默认 request body 限制是 500KB,需提前在配置里调大
MAX_CONTENT_LENGTH)
预览第 n 页时,如何避免索引越界或白页
PyMuPDF 的页码从 0 开始,但用户请求的页码(如 URL 中的 /preview?pdf=xxx&page=1)习惯从 1 开始。直接用 doc[page] 会抛 IndexError,且某些 PDF 的 doc.page_count 可能为 0(空文档或元数据异常)。
务必先校验:
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
page_num = int(request.args.get("page", "1")) - 1
if not (0 page = doc[page_num] # 此时才取
另外,有些 PDF 页面内容为空(page.get_text() == "" 且 page.get_image_info() == []),这时 get_pixmap() 可能返回全黑或极小尺寸图像 —— 建议加 fallback:若 pix.width ,直接返回占位 PNG。
为什么本地能跑通,部署到Gunicorn/uWSGI后图片变紫/偏色
这是 PyMuPDF 的色彩空间陷阱:get_pixmap() 默认按 PDF 内置色彩空间输出(可能是 CMYK、Gray 或带 Alpha 的 RGB),而 PIL.Image.frombytes("RGB", ...) 强制解释为 RGB,导致通道错位(典型表现是文字发紫、背景泛青)。
正确做法是让 PyMuPDF 统一转成 sRGB 并展平 Alpha:
pix = page.get_pixmap(dpi=120, colorspace=fitz.csRGB, alpha=False)
注意:colorspace=fitz.csRGB 是关键;alpha=False 避免透明通道干扰 PIL 解码。如果 PDF 原生是灰度图,csRGB 仍能正确转换,无需单独判断。
真正麻烦的是某些扫描PDF含专色(Spot Color)或自定义 ICC 配置 —— 这种情况 PyMuPDF 无法完美还原,建议前端加提示:“该文档含专业印刷色,预览效果可能与实际略有差异”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










