使用FileReader上传数据大小超出原文件长度的原因排查
问题原因与解决方法
核心问题
readAsBinaryString的缺陷:该方法读取的二进制字符串本质是UTF-8编码的文本,传递给$.ajax时,jQuery会默认对字符串进行编码转换,破坏原始二进制文件的字节结构,导致文件体积变大且损坏。- jQuery默认逻辑不兼容二进制:直接传递字符串形式的二进制数据,jQuery会自动尝试将其转为URL编码格式,进一步篡改数据。
修复方案
方案一:改用ArrayBuffer读取并通过Blob传递
ArrayBuffer能完整保留原始二进制数据,配合Blob传递可避免编码问题:
修改readfile函数:
function readfile() { var file = $("#excelFile")[0].files[0]; var reader = new FileReader(); reader.addEventListener("load", (event) => { // 将ArrayBuffer转为Blob,保留原始文件类型 const blob = new Blob([event.target.result], { type: file.type }); restPutPost("post", "rest/mapping", blob, function(data) { console.log(`File ${file.name} uploaded.`); }, function(xhr, status, error) { console.log(`Upload failed: ${error}`); }, file.type); }); reader.readAsArrayBuffer(file); // 替换readAsBinaryString }
同时更新restPutPost函数,添加二进制数据处理逻辑:
function restPutPost(method, url, body, callback = null, errorcallback = null, contenttype = "application/json") { let actualbody = body; let processData = true; if (contenttype === "application/json") { actualbody = body != null ? JSON.stringify(body) : null; } else if (body instanceof Blob || body instanceof FormData) { // 二进制数据禁止自动处理 processData = false; // Blob类型自动获取contenttype(如果未传入) if (!contenttype && body instanceof Blob) { contenttype = body.type; } } $.ajax({ type: method, url: url, headers: { Accept: "application/json" }, data: actualbody, contentType: contenttype || false, processData: processData, // 关键配置:禁用数据处理 success: function (data) { callback?.(data); }, error: function (xhr, status, error) { errorcallback?.(xhr, xhr.status, error); } }); }
方案二:直接使用FormData上传(最简便)
FormData是浏览器原生的文件上传对象,自动处理二进制编码,无需手动读取文件:
function readfile() { var file = $("#excelFile")[0].files[0]; const formData = new FormData(); formData.append("file", file); // "file"需与接口接收的参数名一致 restPutPost("post", "rest/mapping", formData, function(data) { console.log(`File ${file.name} uploaded.`); }, function(xhr, status, error) { console.log(`Upload failed: ${error}`); }, false); // 传入false让浏览器自动设置Content-Type }
此方案下,前面更新的restPutPost函数已经能正确处理FormData类型。
内容的提问来源于stack exchange,提问作者Bart Friederichs
相关产品推荐
相关产品推荐

