Django视图用reportlab.pdfgen生成损坏PDF的问题排查
PDF损坏问题的修复方案
核心原因:响应未写入PDF内容
你生成PDF的逻辑没问题,但最后没把缓冲区里的PDF数据传给HttpResponse,导致返回的文件是空的,自然损坏。
修复步骤:在pdf.save()之后,添加以下代码:
# 把缓冲区指针移到开头,准备读取内容 buffer.seek(0) # 将PDF内容写入响应 response.write(buffer.getvalue())
其他需要修复的细节问题
1. 标题字符串未格式化
你写的标题是硬编码的字符串模板,不会替换变量值,会直接显示{org.name}这类文本。改成f-string:
pdf.drawString(100,800, f"{org.name} - {report.year} {report.report_type.standard} - {report.report_type.name} Report")
2. 内容溢出页面
当导出的答案数量太多时,y坐标会减到负数,内容会画出页面范围,甚至导致PDF生成异常。需要加分页逻辑:
for answer in answers_to_export: # 当y坐标低于页面底部阈值时,新建页面 if y < 100: pdf.showPage() # 重置字体和y坐标,重新绘制表头 pdf.setFont("Helvetica", 12) y = 750 for header in headers: pdf.drawString(100, y, header) y -= 25 # 原有的绘制答案代码...
3. 异常处理缺失依赖
你的except块里用了log.error(traceback.print_exc()),但没导入traceback和logging模块,会触发新错误。添加导入:
import traceback import logging log = logging.getLogger(__name__)
另外,尽量避免裸except,建议捕获具体异常类型(比如Report.DoesNotExist等),防止隐藏未知问题。
4. 文件名特殊字符兼容
如果组织名称包含空格、中文等特殊字符,浏览器可能无法正确解析文件名。用urllib.parse.quote()转义:
from urllib.parse import quote filename = f"{org.name}_{report.report_type.standard}_report_{report.year}_export_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf" # 使用UTF-8编码的文件名格式,兼容特殊字符 response["Content-Disposition"] = f"attachment; filename*=UTF-8''{quote(filename)}"
5. 页脚位置错误
letter页面高度是792点,你把页脚放在y=700的位置,会和顶部的标题重叠。调整到页面底部:
def add_pdf_footer(pdf): date_str = datetime.now().strftime("%Y-%m-%d") pdf.saveState() width, height = letter pdf.setFont("Helvetica", 9) text = f"Exported on {date_str}" pdf.drawRightString(width - 50, 30, text) # 移到y=30的底部位置 pdf.restoreState()
内容的提问来源于stack exchange,提问作者Chris B.
相关产品推荐
相关产品推荐

