You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以Raw POST方式发送二进制数据?POST数据量异常排查

问题:POST二进制数据时请求数据量与实际文件大小不符

我使用以下代码向REST接口以POST方式发送二进制数据:

var file = $("#file-to-upload")[0].files[0];
var filename = file.name;
var url = "/upload";
const reader = new FileReader();
reader.onload = function(e) {
    console.log(`Read file data: length: ${e.target.result.length}`);
    $.post({
        url: url, 
        data: e.target.result, 
        headers: {
            "Content-Type": "application/octet-stream",
            "Content-Disposition": `attachment; filename=${filename}`
        },
        success: function(r) {
            console.log(r);
        }
    }).fail(function(xhr, status, error) {
        console.log(xhr);
    });
}
reader.readAsBinaryString(file);

控制台正确显示了文件的字节数,但在开发者工具中查看实际POST请求时,发现发送的数据量更多。e.target.result是未序列化的二进制字符串,但开发者控制台显示为26.8kB,而字符串长度为12817。请问我忽略了什么?


原因与解决方案

问题根源

  1. readAsBinaryString的局限性:这个方法返回的二进制字符串,本质是把每个字节转成对应ASCII字符,但遇到ASCII范围外的字节(如0x80及以上),会生成无法被正确识别的“占位字符”。jQuery处理该字符串时,会自动用UTF-8编码这些字符,单个字节会被转成2-3个字节,直接导致数据量膨胀。
  2. jQuery$.post的默认编码行为:即便手动设置Content-Type为application/octet-stream,jQuery的AJAX方法默认仍会把数据当成application/x-www-form-urlencoded格式处理,对字符串进行编码,进一步增加数据体积。

正确解决方案

方案1:使用FormData(最简便,推荐)

FormData可直接封装文件对象,浏览器会自动处理二进制数据的编码和Content-Type设置,完全避免手动处理的问题:

var file = $("#file-to-upload")[0].files[0];
var url = "/upload";
var formData = new FormData();
formData.append('file', file);

$.ajax({
    url: url,
    type: 'POST',
    data: formData,
    processData: false,  // 禁止jQuery自动处理数据格式
    contentType: false,  // 让浏览器自动生成包含boundary的Content-Type
    success: function(r) {
        console.log(r);
    },
    error: function(xhr, status, error) {
        console.log(xhr);
    }
});

方案2:使用ArrayBuffer直接发送二进制

如果必须手动设置Content-Disposition这类请求头,可以用readAsArrayBuffer读取文件,再通过原生XMLHttpRequest发送,绕开jQuery的自动编码:

var file = $("#file-to-upload")[0].files[0];
var filename = file.name;
var url = "/upload";
const reader = new FileReader();
reader.onload = function(e) {
    console.log(`Read file data: length: ${e.target.result.byteLength}`);
    const xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.setRequestHeader("Content-Type", "application/octet-stream");
    xhr.setRequestHeader("Content-Disposition", `attachment; filename=${filename}`);
    xhr.onload = function() {
        if (xhr.status >= 200 && xhr.status < 300) {
            console.log(xhr.responseText);
        } else {
            console.log(xhr);
        }
    };
    xhr.send(e.target.result); // 直接发送ArrayBuffer二进制数据
}
reader.readAsArrayBuffer(file);

内容的提问来源于stack exchange,提问作者Bart Friederichs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:05:34