正确构建多部分文件有效内容

时间:2014-01-26 00:41:29

标签: javascript xmlhttprequest multipartform-data

我通过以下方式通过多部分POST请求发送二进制文件:

var xhr = new XMLHttpRequest();
body = '--' + boundary + '\r\n'
             + 'Content-Disposition: form-data; name="file"; '
             + 'filename="temp.bin"\r\n'
             + 'Content-type: application/octet-stream\r\n\r\n'
             + encryptedFileContent + '\r\n'
             + '--' + boundary + '--';
xhr.open("POST", "http://localhost:999/some/path", true);
xhr.setRequestHeader("Content-type", "multipart/form-data; boundary="+boundary);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200)
        console.log("File uploaded!");
}
xhr.send(body);

我在Chrome打包应用程序中发送它,我之所以以这种方式发送文件是因为最初文件是通过FileReader从本地文件系统读取的,然后它被加密后才会被加密提交。 encryptedFileContent按以下方式构建:

var reader = new FileReader();
reader.onload = function(e) {
     var plainArray = Array.apply([], new Int8Array(e.target.result));
     var encryptedArray = encrypt(plainArray);
     var encryptedFileContent="";
     for (var i=0; i<encryptedArray.length; i++) { 
          encryptedFileContent+=String.fromCharCode(encryptedArray[i]) 
     }
}
reader.readAsArrayBuffer(file);

调试,我可以看到encryptedArray包含以下值:

[ 70, -21, -15, ... ]

在服务器端,当读取数组时,我希望看到相同的数据,但我看到了:

[ -17, -66, -112, ... ]

看起来我为二进制文件构建有效负载的方式不正确。问题是String.fromCharCode吗?

1 个答案:

答案 0 :(得分:0)

服务器上接收的字节数组不同的原因是有效负载转换为unicode并编码为utf-8。 为了在没有任何转换的情况下发送数据,您应该以二进制形式发送数据,如下所述:

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest?redirectlocale=en-US&redirectslug=DOM%2FXMLHttpRequest%2FUsing_XMLHttpRequest#Submitting_forms_and_uploading_files

if (!XMLHttpRequest.prototype.sendAsBinary) {
    XMLHttpRequest.prototype.sendAsBinary = function(sData) {
        var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);
        for (var nIdx = 0; nIdx < nBytes; nIdx++) {
            ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;
        }
        /* send as ArrayBufferView...: */
        this.send(ui8Data);
        /* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */
    };
}