我必须为将来的项目(无闪光灯,IE10 +,FF7 +等)创建一个图像上传器,它在客户端而不是服务器上进行图像大小调整/转换/裁剪。
所以我创建了一个javascript界面,用户可以“上传”他们的文件并直接在浏览器中调整大小/裁剪,而无需联系服务器。性能还可以,不是那么好,但它确实有效。
endresult是一个canvas元素数组。用户可以在调整大小后编辑/裁剪图像,因此我将它们保留为画布而不是将它们转换为jpeg。 (这将使初始表现恶化)
现在这很好用,但我不知道现在将完成的canvas元素实际上传到服务器的最佳方法是什么。 (在服务器上使用asp.net 4通用处理程序)
我尝试从包含每个画布的dataurl的所有元素创建一个json对象。
问题是,当我得到10-40张图片时,浏览器会在创建dataurls时开始冻结,特别是对于大于2兆字节的图片。
//images = array of UploadImage
for (var i = 0; i < images.length; i++) {
var data = document.getElementById('cv_' + i).toDataURL('image/jpg');
images[i].data = data.substr(data.indexOf('base64') + 7);
}
同样将它们转换为json对象(我使用的是json2.js)通常会导致我的浏览器崩溃。 (FF7)
我的对象
var UploadImage = function (pFileName, pName, pDescription) {
this.FileName = pFileName;
this.Name = pName;
this.Description = pDescription;
this.data = null;
}
上传例程
//images = array of UploadImage
for (var i = 0; i < images.length; i++) {
var data = document.getElementById('cv_' + i).toDataURL('image/jpg');
images[i].data = data.substr(data.indexOf('base64') + 7);
}
var xhr, provider;
xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function (e) {
console.log(Math.round((e.loaded * 100) / e.total) + '% done');
}, false);
}
provider = function () {
return xhr;
};
var ddd = JSON.stringify(images); //usually crash here
$.ajax({
type: 'POST',
url: 'upload.ashx',
xhr: provider,
dataType: 'json',
success: function (data) {
alert('ajax success: data = ' + data);
},
error: function () {
alert('ajax error');
},
data: ddd
});
将canvas元素发送到服务器的最佳方法是什么?
我应该一次性发送还是逐个发送它们?
答案 0 :(得分:5)
逐个上传文件会更好。需要更少的内存,只要一个文件准备好上传,就可以启动上传,而不是等待所有文件都准备好。
使用FormData
发送文件。允许以二进制格式而不是base64编码上传文件。
var formData = new FormData;
如果Firefox使用canvas.mozGetAsFile('image.jpg')而不是canvas.toDataUrl()。允许避免从base64到二进制的不必要的转换。
var file = canvas.mozGetAsFile('image.jpg');
formData.append(file);
在Chrome中,使用BlobBuilder将base64转换为blob(请参阅dataURItoBlob
函数
接受 在玩了几件事之后,我设法自己解决了这个问题。
首先,这会将dataURI转换为Blob:
//added for quick reference
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
来自this question):
var blob = dataURItoBlob(canvas.toDataURL('image/jpg'));
formData.append(blob);
然后发送formData
对象。我不确定如何在jQuery中执行它,但是使用普通的xhr对象就像这样:
var xhr = new XMLHttpRequest;
xhr.open('POST', 'upload.ashx', false);
xhr.send(formData);
在服务器上,您可以从Files集合中获取文件:
context.Request.Files[0].SaveAs(...);