使用FileReader、图像和画布时,JavaScript内存占用率很高
High JavaScript memory usage with FileReader, images and <canvas>
我正在工作的图像多上传,这听起来不错,但是…一如既往的内存问题。
脚本目标是存活上传100+图像(300Mb+)。所以,如果你会发现(我仍然javascript跛脚)任何问题,请给我一个建议。谢谢。
我代码:CFileReader.prototype.proccessFile = function(cb) {
// this means File
var reader = new FileReader();
reader.readAsDataURL(this);
reader.onload = (function (f) {
return function(e) {
var image = new Image();
image.src = e.target.result;
image.onload = (function(f) {
return function() {
var maxWidth = 700,
maxHeight = 700,
imageWidth = this.width,
imageHeight = this.height;
if (imageWidth > imageHeight) {
if (imageWidth > maxWidth) {
imageHeight *= maxWidth / imageWidth;
imageWidth = maxWidth;
}
}
else {
if (imageHeight > maxHeight) {
imageWidth *= maxHeight / imageHeight;
imageHeight = maxHeight;
}
}
var canvas = document.createElement('canvas');
canvas.width = imageWidth;
canvas.height = imageHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0, imageWidth, imageHeight);
if(typeof cb == 'function') {
cb(f,canvas.toDataURL());
}
delete canvas;
delete ctx;
return;
}
})(f);
};
})(this);
}
我认为窗口。createObjectURL比FileReader快,你应该使用两者与FileReader的回落…您还可以检查每个操作的性能,因为每个浏览器都存在差异,例如http://jsperf.com/canvas-image-resizing并且不要忘记因内存原因而撤销objecturl…你也可以找网络工作者http://www.html5rocks.com/en/tutorials/file/filesystem-sync/toc-readingsync
if("createObjectURL" in window || "URL" in window &&
"createObjectURL" in window.URL || "webkitURL" in window &&
"createObjectURL" in window.webkitURL) {
if("createObjectURL" in window) {
// Chrome exposes create/revokeObjectURL directly on window
objURL = window.createObjectURL(file);
} else if("webkitURL" in window) {
// Chrome exposes create/revokeObjectURL on the new webkitURL API
objURL = window.webkitURL.createObjectURL(file);
} else {
// FF4 exposes create/revokeObjectURL on the new URL API
objURL = window.URL.createObjectURL(file);
}
// RESIZE image
// STORED IN
// objURL
} else {
// fallback to FileReader for FF3.6
reader = new FileReader();
reader.onload = function(event) {
// RESIZE image
// STORED IN
// event.target.result
}
reader.onprogress = function (evt) {
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
console.log(percentLoaded);
}
}
reader.readAsDataURL(file);
}
好吧,几天的谷歌搜索,几个小时的最佳解决方案。(不是有史以来最好的,但是我能想到的最好的)。如果有人有更好的,把它的答案,或者只是给坏名声。
目标一:将所有内容存储在全局空间(canvas,reader,canvas context,image)
window.reader = new FileReader();
window.canvas = document.createElement('canvas');
window.image = new Image();
window.ctx = window.canvas.getContext("2d");
目标二:使用画布。toBlob方法(目前仅在Firefox中实现,您将需要一些polyfill来实现)
目标三:加上一些等待,这个我不能确定地解释,这只是经验。目标是允许浏览器在调用之间调用垃圾回收器。
这是我的最后一个开发脚本:
window.prepareFile = function (index,cb) {
// this means file html element
var res = window.configuration.photo.resolution.split(":");
//var res = [300,200];
var reader = window.reader;
$('#fm-up-status > tr[for="'+this.files[index].name+'"]').children('td')[3].innerHTML = 'Zpracovávám';
reader.readAsDataURL(this.files[index]);
reader.onload = (function (f) {
return function(e) {
setTimeout(function(){
var image = window.image;
image.src = e.target.result;
image.onload = (function(f) {
return function() {
var maxWidth = parseInt(res[0]),
maxHeight = parseInt(res[1]),
imageWidth = this.width,
imageHeight = this.height;
if (imageWidth > imageHeight) {
if (imageWidth > maxWidth) {
imageHeight *= maxWidth / imageWidth;
imageWidth = maxWidth;
}
}
else {
if (imageHeight > maxHeight) {
imageWidth *= maxHeight / imageHeight;
imageHeight = maxHeight;
}
}
var canvas = window.canvas;
canvas.width =0;
canvas.width = imageWidth;
canvas.height = imageHeight;
window.ctx.drawImage(this, 0, 0, imageWidth, imageHeight);
canvas.toBlob(
function (blob) {
var formData = new FormData();
formData.append('file', blob, f.name);
cb(f.name,formData);
},
'image/jpeg'
);
return;
}
})(f);
return;
},500);
};
})(this.files[index]);
return;
}
然后您可以简单地以标准格式(multipar)上传数据,如下所示:
window.uploader = function(filename,formdata,cb) {
$('#fm-up-status > tr[for="'+filename+'"]').children('td')[3].innerHTML = 'Uploaduji';
xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function (evt) {
if (evt.lengthComputable) {
var floatComplete = evt.loaded / evt.total;
window.uploadProgress(filename,floatComplete);
}
}, false);
}
provider = function () {
return xhr;
};
$.ajax({
url: window.uploadUri,
type: "POST",
data: formdata,
xhr: provider,
processData: false,
contentType: false,
dataType: "json",
success: function (res,state,xhr) {
cb(false,res,xhr);
return;
},
error: function (xhr, state, err) {
cb(err,false,xhr)
return;
}
});
};
这段代码真的不适合生产,它是一个简单的概念验证
相关文章:
- 简单对象的Javascript内存泄漏
- Javascript内存分配
- 跟踪 JavaScript 内存泄漏的工具
- 页面刷新后javascript内存泄漏有问题吗?为什么?
- Javascript内存游戏-图像交换
- javascript内存问题
- 在 KnockoutJS 中更改模型数据时出现 Javascript 内存泄漏
- 有没有办法在测试中找到JavaScript内存泄漏
- for 循环中的 JavaScript 内存使用情况
- Javascript 内存泄漏时使用画布和 blob
- 在 express/node.js API 中进行高效的服务器端 JavaScript 内存管理
- Javascript 代码的内存占用
- Javascript内存管理:删除和拼接
- Javascript内存管理(requestAnimationFrame回调)
- JavaScript内存泄漏
- 捕获单页应用程序的JavaScript内存泄漏
- JavaScript内存化只能用于缓存返回的结果吗
- 使用THRE.JS对象的全局数组的Javascript内存管理
- JavaScript 内存泄漏解释
- 匿名JavaScript对象占用内存吗?