【发布时间】:2018-02-05 00:24:26
【问题描述】:
我有一个 AngularJS 代码来执行文件上传。起初我认为它工作正常,但当我尝试上传更大的文件(例如 5 个文件,每个 10 MB)时,我发现这段代码在内存处理方面的性能非常差。
例如:当我附加 5 个文件(每个 10 MB = 总共 50 MB)时,浏览器进程内存需求峰值达到 2 GB!
我已经在 Firefox、Chrome 和 IE 中测试过它。此外,在 Chrome 中,当浏览器进程达到提交的 3 GB 内存时,页面会崩溃。
在 Firefox 中,尝试一次上传超过 80 MB 时,我会在控制台中看到错误:
out of memory
我尝试修改发出实际请求的部分并删除了data: JSON.stringify(formattedData),这是第一个瓶颈。结果发现stringifying 在那里是多余的。
但第二个瓶颈仍然存在,它是函数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;
};
我省略了满足以下要求的部分:
- 检查文件数量(限制为 10)
- 检查每个文件的大小(每个文件限制为 10 MB)
- 检查允许的文件扩展名
- 将其余(文本)数据连同文件一起发送到服务器(ASP.NET MVC 方法)
【问题讨论】:
-
以 json 格式发送文件是个坏主意...使用分段上传(即FormData)
-
使用FormData API,
Content-Type: multipart/form-data的base64 encoding 额外增加了 33% 的开销。如果服务器支持,直接发送文件效率更高。
标签: javascript angularjs file-upload out-of-memory