我正在尝试使用XMLHttpRequest和FileReader将(DICOM)二进制文件上传到服务器。
根据DICOM标准,Content-Type muss是multipart/related;type=application/dicom
定义的,并且在Request Payload中必须再次为Content-Type:application/dicom
,我已设法使用此代码以某种方式构建该结构:
let boundary = Math.random().toString().substr(2);
let reader = new FileReader();
reader.readAsBinaryString(fileList[0]);
reader.onload = function(e) {
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", "myurl", true);
var dashes = '--';
var crlf = "\r\n";
if ( fileList[0].type == '' ){
filetype = 'application/dicom';
} else {
filetype = fileList[0].type;
}
let content = e.target["result"];
var data = dashes + boundary + crlf + "Content-Type: " + filetype + crlf + crlf + content + crlf + dashes + boundary + dashes;
xmlHttpRequest.setRequestHeader("Content-Type", "multipart/related;type=application/dicom;boundary=" + boundary+";");
xmlHttpRequest.setRequestHeader("Accept", "application/dicom+json");
xmlHttpRequest.send(data);
}; xmlHttpRequest.send(data);
};
这种方法的问题在于,似乎XMLHttpRequest进行了UTF-8编码并且破坏了二进制数据(参见this post)。
我的第二个问题是如何使用这种方法处理大文件(大约1 TB)?
答案 0 :(得分:2)
由于post,我找到了对我(第一部分)问题的答案,现在是我的代码:
var boundary = Math.random().toString().substr(2);
var reader = new FileReader();
reader.readAsArrayBuffer(fileList[0]);
reader.onload = function(e) {
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", "myurl", true);
var dashes = '--';
var crlf = "\r\n";
if ( fileList[0].type == '' ){
filetype = 'application/dicom';
} else {
filetype = fileList[0].type;
}
var content = e.target["result"];
var dataView = new DataView(e.target["result"]);
var postDataStart = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + encodeURIComponent(fileList[0].name) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf;
var postDataEnd = crlf + dashes + boundary + dashes;
var size = postDataStart.length + dataView.byteLength + postDataEnd.length;
var uint8Array = new Uint8Array(size);
var i = 0;
for (; i < postDataStart.length; i++) {
uint8Array[i] = postDataStart.charCodeAt(i) & 0xFF;
}
for (let j = 0; j < dataView.byteLength; i++, j++) {
uint8Array[i] = dataView.getUint8(j);
}
for (let j = 0; j < postDataEnd.length; i++, j++) {
uint8Array[i] = postDataEnd.charCodeAt(j) & 0xFF;
}
var payload = uint8Array.buffer;
xmlHttpRequest.setRequestHeader("Content-Type", "multipart/related;type=application/dicom;boundary=" + boundary+";");
xmlHttpRequest.setRequestHeader("Accept", "application/dicom+json");
xmlHttpRequest.send(payload);
};
修改强>
我找到了另一种解决方案,它使用较大的文件作为可用的RAM,并且流式传输文件而不是首先加载到RAM中:
var boundary = Math.random().toString().substr(2);
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", "myurl", true);
var dashes = '--';
var crlf = "\r\n";
filetype = fileList[0].type;
var postDataStart = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + encodeURIComponent(fileList[0].name) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf;
var postDataEnd = crlf + dashes + boundary + dashes;
xmlHttpRequest.setRequestHeader("Content-Type", "multipart/related;type=application/dicom;boundary=" + boundary+";");
xmlHttpRequest.setRequestHeader("Accept", "application/dicom+json");
xmlHttpRequest.send(new Blob([new Blob([postDataStart]),fileList[0], new Blob([postDataEnd])]));