我有一个AngularJS代码来执行文件上传。起初我认为它工作正常但是当我尝试上传更大的文件(例如5个文件,每个10 MB)时,我发现这个代码在内存处理方面表现很差。
例如:当我附加5个文件(每个10 MB =总共50 MB)时,峰值浏览器进程内存需求达到2 GB!
我已经在Firefox,Chrome和IE中对它进行了测试。此外,在浏览器进程达到3 GB内存时Chrome中,页面崩溃。
在Firefox中,我可以在尝试一次上传超过80 MB时在控制台中看到错误:
out of memory
我试图修改实际请求所在的部分data: JSON.stringify(formattedData)
,这是第一个瓶颈。事实证明stringify
在那里是多余的。
但是第二个瓶颈仍然存在,即函数binArrayToJson
,它接受ArrayBuffer并将数据读入字节数组。
var binArrayToJson = function (binArray) {
var str = [binArray.length];
for (var i = 0, binLength = binArray.length; i < binLength; i++) {
str[i] = binArray[i];
}
return str;
}
var applyAttachments = function (data1) {
angular.forEach(data1,
function (value, key) {
if (key === "Attachments") {
for (var i = 0; i < value.length; i++) {
if (value[i].file) { //already saved item don't contain 'file' property
var reader = new FileReader();
reader.onloadend = (function (f) {
return function (result) {
var arrayBuffer = result.target.result;
value[f].fileContent = binArrayToJson(new Uint8Array(arrayBuffer));
value[f].isUploaded = true;
};
})(i);
reader.readAsArrayBuffer(value[i].file);
}
}
}
});
};
var createMVCModel = function (output) {
var defaultStringValue = "";
return {
id: output.id,
Name: output.name || defaultStringValue,
Status: output.status || "Draft",
Date: output.date || null
Attachments: output.attachments || []
};
};
var saveModel = function (data, url) {
var formattedData = createMVCModel(data);
var deferred = $q.defer();
applyAttachments(formattedData);
var check = function () {
if (allNewFilesUploaded(formattedData) === true) {
$http({
url: url,
method: "POST",
data: formattedData,
headers: { 'Content-Type': undefined }
})
.then(function (result) {
deferred.resolve(result);
},
function (result) {
deferred.reject(result);
});
} else {
setTimeout(check, 1000);
}
}
check();
return deferred.promise;
};
我省略了满足以下要求的部分:
答案 0 :(得分:0)
$http.post
请求
为避免内存问题,直接发送文件:
$scope.upload = function(url, fileList) {
var config = { headers: { 'Content-Type': undefined },
transformResponse: angular.identity
};
var promises = fileList.map(function(file,index) {
config.params = {'n': index, 'name': file.name};
return $http.post(url, file, config);
});
return $q.all(promises);
};
发送带有File object的POST时,设置'Content-Type': undefined
非常重要。然后,XHR send method会检测File object并自动设置内容类型。