C#传输docx文件至客户端出现大小不一致致文件损坏
问题分析与解决方案
核心原因
jQuery的AJAX默认会将响应内容当作UTF-8字符串处理,即便你设置了responseType: 'arraybuffer',它也会先把二进制数据转成字符串,再转回ArrayBuffer时会破坏原始二进制字节(比如docx这类非文本格式文件),最终导致文件大小异常、损坏无法打开。
解决方案
方案1:改用原生XMLHttpRequest(推荐)
直接使用原生XHR可以避免jQuery的自动转码干扰,确保二进制数据完整:
var xhr = new XMLHttpRequest(); xhr.open('POST', '/exportDataForDocument', true); xhr.responseType = 'arraybuffer'; // 发送JSON数据时需设置对应Content-Type xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = function() { if (xhr.status === 200) { var fileName = "sample.docx"; var blob = new Blob([xhr.response], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }); console.log("Byte length of the Blob: " + blob.size + " bytes"); // 下载逻辑 var isIE = !!document.documentMode; if(isIE) { window.navigator.msSaveBlob(blob, fileName); } else { var url = window.URL || window.webkitURL; var link = url.createObjectURL(blob); var aDown = document.createElement("a"); aDown.download = fileName; aDown.href = link; document.body.appendChild(aDown); aDown.click(); document.body.removeChild(aDown); // 释放URL对象,避免内存泄漏 url.revokeObjectURL(link); } } }; xhr.send(JSON.stringify(result));
方案2:修改jQuery AJAX配置(保留jQuery时使用)
通过自定义xhr对象和dataFilter,强制jQuery不处理二进制响应:
$.ajax({ type: "POST", url: '/exportDataForDocument', data: JSON.stringify(result), contentType: 'application/json', // 自定义XHR对象,设置responseType xhr: function() { var xhr = new XMLHttpRequest(); xhr.responseType = 'arraybuffer'; return xhr; }, // 跳过jQuery的响应数据处理,直接返回原始数据 dataFilter: function(data) { return data; }, success: function(data, textStatus, xhr) { var fileName = "sample.docx"; var blob = new Blob([data], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }); console.log("Byte length of the Blob: " + blob.size + " bytes"); // 下载逻辑 var isIE = !!document.documentMode; if(isIE) { window.navigator.msSaveBlob(blob, fileName); } else { var url = window.URL || window.webkitURL; var link = url.createObjectURL(blob); var aDown = $("<a />"); aDown.attr("download", fileName); aDown.attr("href", link); $("body").append(aDown); aDown[0].click(); aDown.remove(); url.revokeObjectURL(link); } } });
额外注意事项
- 服务端代码本身没有问题,
File.ReadAllBytes读取的是完整文件,Content-Length设置正确,无需修改。 - 发送JSON数据时必须设置
Content-Type: application/json,确保服务端能正确解析请求体。 - 下载完成后调用
URL.revokeObjectURL释放内存,避免浏览器内存泄漏。
内容的提问来源于stack exchange,提问作者Sawan Meshram
相关产品推荐
相关产品推荐

