How to upload / post multiple canvas elements

I need to create an image downloader for a future project (no flash, IE10 +, FF7 +, etc.) that resizes / converts / crop images on the client side, not on the server.

So, I created a javascript interface in which the user can "upload" their files and resize / crop in the browser directly, without communicating with the server. Performance is fine, not so good, but it works.

The end result is an array of canvas elements. The user can edit / crop the images after changing them, so I save them as a canvas, and not convert them to jpeg. (Which will degrade initial performance)

Now this works fine, but I don’t know what is the best way to actually upload ready-made canvas elements to the server. (Using the asp.net 4 generic handler on the server)

I tried to create a json object from all the elements containing the dataurl of each canvas.

The problem is that when I get 10-40 pictures, the browser starts to freeze when creating dataurls, especially for images larger than 2 megabytes.

//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); } 

Also converting them to a json object (I use json2.js) usually causes my browser to crash. (Ff7)

My object

  var UploadImage = function (pFileName, pName, pDescription) { this.FileName = pFileName; this.Name = pName; this.Description = pDescription; this.data = null; } 

Boot program

  //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 }); 

What would be the best way to send canvas elements to the server?

Should I send them all at once or one by one?

+7
source share
1 answer

Uploading files one at a time is better. Less memory is required, and as soon as one file is ready for download, the download can be started rather than wait until all files are prepared.

Use FormData to submit files. Allows you to download files in binary format instead of base64 encoding.

 var formData = new FormData; 

If Firefox uses canvas.mozGetAsFile ('image.jpg') instead of canvas.toDataUrl (). Avoid unnecessary conversion from base64 to binary.

 var file = canvas.mozGetAsFile('image.jpg'); formData.append(file); 

Chrome uses BlobBuilder to convert base64 to blob (see dataURItoBlob function

accepted Having played with a few things, I managed to figure it out myself.

First of all, it converts dataURI to 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}); } 

From this question ):

 var blob = dataURItoBlob(canvas.toDataURL('image/jpg')); formData.append(blob); 

And then submit the FormData object. I'm not sure how to do this in jQuery, but with a simple xhr object it is like this:

 var xhr = new XMLHttpRequest; xhr.open('POST', 'upload.ashx', false); xhr.send(formData); 

On the server, you can receive files from a collection of files:

 context.Request.Files[0].SaveAs(...); 
+5
source

All Articles