Django+Ajax点击按钮下载二进制文件返回数据异常问题
解决AJAX下载二进制文件体积异常增大的问题
我之前碰到过一模一样的坑!你现在的问题核心是jQuery AJAX默认会把响应内容当成UTF-8字符串解析,而你的.kdb是二进制文件,里面包含大量非UTF-8兼容的字节,转成字符串再转回二进制的过程中会被错误编码,导致文件体积莫名变大(比如单个字节被拆成多个)。虽然Network面板里的Content-Length显示正确,但前端拿到的已经是被篡改后的内容了。
问题根源
你代码里注释掉了responseType: 'arraybuffer',就算打开这个配置,jQuery的AJAX也没法正确处理——因为它的默认逻辑会强制把响应转换成字符串,直接破坏二进制数据的完整性。
最优解决方案:改用原生XMLHttpRequest处理
原生XHR对二进制数据的支持更直接可靠,能完美避开jQuery的自动解析坑。修改你的按钮点击事件代码如下:
$('#btn_gen').on('click',function(e) { console.log("Generate clicked"); const json = { 'sessn' : global_sessn, 'fn' : $('#kdb_sel').val(), 'xml' : $('#kdb_xml').val() }; // 显示加载弹窗 $('#loading').modal({backdrop: "static"}); const xhr = new XMLHttpRequest(); xhr.open('POST', "ajx_generate"); xhr.setRequestHeader("X-CSRFToken", '{{ csrf_token }}'); xhr.setRequestHeader("Content-Type", "application/json"); // 关键配置:直接把响应处理成Blob对象 xhr.responseType = 'blob'; xhr.onload = function() { $('#loading').modal('hide'); if (xhr.status === 200) { console.log("fun_succ1 success"); const blob = xhr.response; const a = document.createElement('a'); const url = (window.URL || window.webkitURL).createObjectURL(blob); a.href = url; a.download = $('#kdb_sel').val(); document.body.append(a); a.click(); a.remove(); window.URL.revokeObjectURL(url); } else { // 触发失败回调 fun_fail1(); } }; xhr.onerror = function() { $('#loading').modal('hide'); fun_fail1(); }; xhr.send(JSON.stringify(json)); });
为什么这个方案有效?
- 原生XHR的
responseType: 'blob'会直接把服务器返回的二进制数据封装成Blob对象,全程不做任何字符串转码,完全保留原始字节。 - 彻底避开了jQuery AJAX的自动解析逻辑,从根源上杜绝了二进制数据被篡改的可能。
可选:如果坚持用jQuery处理
要是你不想换掉jQuery,可以注册一个自定义的dataType转换器,强制让它返回原始二进制数据:
// 先注册binary类型的转换器 $.ajaxSetup({ converters: { '* binary': function(data) { return data.response; } } }); // 修改请求配置 var req = { url: "ajx_generate", method: "post", processData: false, contentType: "application/json", // 这里你之前设为false是错误的,发送JSON需要指定这个类型 headers: { "X-CSRFToken": '{{ csrf_token }}' }, data: JSON.stringify(json), responseType: 'blob', dataType: 'binary' };
不过相比之下,原生XHR的方案更简洁可靠,不容易踩额外的坑。
修改后测试一下,你会发现下载的文件大小和服务器端的原始文件完全一致了!
内容的提问来源于stack exchange,提问作者Shashi
相关产品推荐
相关产品推荐

