
在 django web 应用中,当需要根据用户提交的数据动态生成 pdf 文件并提供下载功能时,常见做法是利用 io.bytesio 在内存中构建 pdf 内容,然后通过 django.http.fileresponse 将其发送给客户端。这种方法在本地开发环境中通常运行良好,但在部署到如 apache 这样的生产服务器(尤其通过 cpanel python web app 托管时)后,可能会遇到 io.unsupportedoperation: fileno 错误。
具体表现为:前端 J*aScript 发起 GET 请求下载 PDF,控制台显示通用错误,而服务器的 stderr.log 文件中记录了 io.UnsupportedOperation: fileno 异常。尽管前端 J*aScript 与后端 Django 函数之间的基本通信(例如,简单地返回一个字符串)是正常的,但涉及 PDF 文件生成和传输时就会出现问题。
原始的 Django PDF 生成视图代码示例如下:
import io
from django.http import FileResponse
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import letter
def generate_pdf(request, id):
buffer = io.BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=letter)
# 此处省略了根据数据库数据生成PDF内容的ReportLab代码
# 例如:doc.build(elements)
buffer.seek(0) # 将缓冲区指针移到开头
return FileResponse(buffer, as_attachment=True, filename="gen_pdf.pdf")前端 J*aScript 代码负责发起 AJAX 请求并处理下载:
function downloadPDF(id, date) {
const csrftoken = getCookie('csrftoken'); // 获取CSRF token
$.ajax({
url: `/generate-pdf/${id}`,
method: 'GET',
headers: {
'X-CSRFToken': csrftoken,
},
mode: 'same-origin',
xhrFields: {
responseType: 'blob' // 指定响应类型为 blob
},
success: function(response) {
console.log(response);
var url = URL.createObjectURL(response); // 创建一个临时URL
var link = document.createElement('a');
link.href = url;
link.download = `${id}-${date}.pdf`; // 设置下载文件名
link.click(); // 触发下载
URL.revokeObjectURL(url); // 清理临时URL
},
error: function(xhr, status, error) {
console.error('Error generating PDF:', error);
// 错误处理
}
});
}经过排查,发现 io.UnsupportedOperation: fileno 错误并非直接由 io.BytesIO 引起,而是当生成的 PDF 文件过大时,FileResponse 在某些生产环境配置下,可能尝试以类似文件系统的方式(例如,通过 fileno() 方法获取文件描述符)处理这个巨大的内存缓冲区,而 io.BytesIO 对象并不支持 fileno() 操作,从而导致异常。更深层次的原因是,将整个大文件加载到内存中,超出了服务器为单个进程分配的内存限制,导致应用崩溃或无法正常响应。本地环境由于资源限制相对宽松,可能不会立即暴露这个问题。
为了解决大文件在内存中传输的问题,我们应该采用分块传输(Chunked Transfer)机制。Django 的 FileResponse 能够与实现了文件迭代器协议的对象协同工作,从而避免一次性将整个文件加载到内存中。wsgiref.util.FileWrapper 正是为此目的而设计。它接收一个文件类对象(如 io.BytesIO 或实际的文件句柄),并将其封装成一个迭代器,以便 WSGI 服务器可以分块读取和发送文件内容。
广研企业网站管理系统中英文双语版
v1.8新增功能简介: 一、后台新增生成网站地图和生成Sitemap.xml的功能。 二、新增下载中心功能,可在后台上传doc,xls,ppt,rar,pdf文件。
三、新增产品缩略图自动缩放功能,图片按比例缩放,解决了图片变形问题。 四、新闻、产品详细页新增了上一个、下一个的功能,改善用户体验。 五、在线客服新增了阿里巴巴贸易通在线客服。 六、可在后台设置分享代码,如百度分享和AddThis等。
0
查看详情
以下是使用 wsgiref.util.FileWrapper 改进后的 Django 视图代码:
import io
from django.http import FileResponse
from reportlab.platypus import SimpleDocTemplate
from reportlab.lib.pagesizes import letter
from wsgiref.util import FileWrapper # 导入 FileWrapper
def generate_pdf(request, id):
buffer = io.BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=letter)
# 此处省略了根据数据库数据生成PDF内容的ReportLab代码
# 例如:doc.build(elements)
# 确保在生成PDF内容后,缓冲区指针位于文件末尾
# 将缓冲区指针移到开头,以便 FileWrapper 从头开始读取
buffer.seek(0)
# 使用 FileWrapper 封装缓冲区,实现分块传输
wrapper = FileWrapper(buffer)
# 创建 FileResponse 对象
response = FileResponse(wrapper, content_type='application/pdf')
# 设置 Content-Disposition 头部,指示浏览器下载文件
response['Content-Disposition'] = 'attachment; filename="gen_pdf.pdf"'
# 设置 Content-Length 头部,告知浏览器文件大小,有助于下载进度显示
response['Content-Length'] = buffer.tell() # buffer.tell() 获取当前指针位置,即文件大小
return response代码解析:
在 Django 应用中处理大文件下载,尤其是在生产环境中,需要特别注意内存效率。io.UnsupportedOperation: fileno 错误往往是大文件处理不当的信号。通过采纳 wsgiref.util.FileWrapper 实现分块传输,可以有效地避免内存溢出,确保即便面对大尺寸 PDF 文件,也能提供稳定、可靠的下载服务。这一实践不仅提升了应用的健壮性,也优化了用户体验。
以上就是解决 Django 应用在 Apache 上生成大文件 PDF 下载失败的问题的详细内容,更多请关注其它相关文章!
相关文章:
外媒分析《GTA6》定价:卖100美元可以但真没必要!
PHP表单数据传递:如何通过隐藏输入字段获取动态ID
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
机构:以往存储涨价周期小米利润率实际上有所改善 能转嫁给消费者等
服务端验证_j*ascript输入检查
QQ邮箱正确登录入口_QQ邮箱官方网站使用地址
J*a实现学校排课程序_面向对象结构化项目示例
TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法
Win11怎么合并任务栏图标 Win11开启任务栏合并减少图标占空间【方法】
vivo手机互传视频怎么操作_vivo手机互传视频详细传输方法
html两个JS只运行一个怎么办_让双JS在html中都运行方法【技巧】
Node.js中HTML按钮与J*aScript函数交互的正确姿势
Golang如何处理RPC请求负载均衡_Golang RPC请求负载均衡策略与实践
lar*el怎么安全地存储和获取配置文件中的敏感信息_lar*el敏感信息安全存储方法
如何在J*a中使用Locale处理多语言环境
苹果手机如何防止被恶意App追踪
三星ZFold5多任务卡顿_Samsung ZFold5流畅度提升
Win11文件资源管理器卡顿怎么修 Win11重置资源管理器进程优化响应速度【修复方法】
PHP高效扁平化嵌套数组:使用array_merge与数组解包操作符
J*a里如何使用forEach遍历Map_Map遍历方法说明
汽水音乐在线解析 汽水音乐在线解析入口
Go语言中Map值调用指针接收器方法的限制与应对
红果短剧网页版官网入口 官方最新网址发布
初次安装JDK时环境变量如何正确配置_J*A_HOME与PATH设置规则讲解
Win10如何开启蓝牙功能_Windows10找不到蓝牙开关解决方法
深入理解与实现最大堆的Heapify过程:常见错误与修正
如何在网页中实现特定地点的随机图片展示
夸克浏览器图书入口 夸克手机浏览器阅读入口
C#使用XPath查询节点时出错? 常见语法错误与调试技巧
虫虫漫画精品漫画官网_虫虫漫画精品漫画官网进入精品漫画
微博网页版怎么开启两步验证_微博网页版账号安全两步验证设置方法
解决PHP会话Cookie在跨域请求中不保留的问题
一加手机拍照效果不好怎么办 一加哈苏影像调校与专业模式使用教程【高手篇】
优化Lar*el Docker镜像:Composer与PHP版本控制策略
J*aScript map 迭代中检测空数组元素的有效方法
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
c++如何使用chrono库处理时间_c++标准库时间与日期操作
Win11输入法不见了怎么办_Windows11恢复语言栏显示方法
J*aScript中安全有效地处理localStorage字符串数据
蛙漫安全无毒 官方认证的绿色入口
夸克浏览器网页版最新地址 夸克浏览器官方入口合集
“音游” × “怪文书” 题材的节奏冒险游戏 《晕晕电波症候群》确定于2026年4月发售!
C++如何实现一个装饰器模式_C++设计模式之动态地给对象添加额外职责
韩小圈电脑版在线入口_网页版免费登录地址
Lar*el如何生成PDF或Excel文件_Lar*el文档导出工具与使用教程
TikTok国际版官网直达_TikTok国际版官网直达进入在线观看
《主播少女的秘密账号迷宫》首支宣传片
抖音网页版企业服务中心登录入口_抖音网页版企业登录平台
解决Rails应用中内容错位与Turbo警告:meta标签误用导致富文本渲染异常
12306选座系统怎么选连座_12306选座多人连坐操作方法