Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert HTML5 Canvas into File to be uploaded?

The standard HTML file upload works as follows:

<g:form method="post" accept-charset="utf-8" enctype="multipart/form-data"        name="form" url="someurl">      <input type="file" name="file" id="file" />  </form> 

In my case I loaded an image into a html5 canvas and want to submit it as a file to the server. I can do:

var canvas; // some canvas with an image var url = canvas.toDataURL(); 

This gives me a image/png as base64.

How can I send the base64 image to the server the same way it is done with the input type file?

The problem is that the base64 file is not of the same type as the file, which is inside the input type="file".

Can I convert the base64 that the types are the same for the server somehow?

like image 379
confile Avatar asked Sep 26 '13 15:09

confile


People also ask

How do I save a canvas file in HTML?

You can save a canvas to an image file by using the method canvas. toDataURL() , that returns the data URI for the canvas' image data. The method can take two optional parameters canvas.

How do I convert a canvas object to an image?

function convertCanvasToImage() { let canvas = document. getElementById("canvas"); let image = new Image(); image. src = canvas. toDataURL(); return image; } let pnGImage = convertCanvasToImage(); document.

What can you do with HTML5 canvas?

The HTML <canvas> element is used to draw graphics, on the fly, via JavaScript. The <canvas> element is only a container for graphics. You must use JavaScript to actually draw the graphics. Canvas has several methods for drawing paths, boxes, circles, text, and adding images.


2 Answers

For security reasons, you can't set the value of a file-input element directly.

If you want to use a file-input element:

  1. Create an image from the canvas (as you've done).
  2. Display that image on a new page.
  3. Have the user right-click-save-as to their local drive.
  4. Then they can use your file-input element to upload that newly created file.

Alternatively, you can use Ajax to POST the canvas data:

You asked about blob:

var blobBin = atob(dataURL.split(',')[1]); var array = []; for(var i = 0; i < blobBin.length; i++) {     array.push(blobBin.charCodeAt(i)); } var file=new Blob([new Uint8Array(array)], {type: 'image/png'});   var formdata = new FormData(); formdata.append("myNewFileName", file); $.ajax({    url: "uploadFile.php",    type: "POST",    data: formdata,    processData: false,    contentType: false, }).done(function(respond){   alert(respond); }); 

Note: blob is generally supported in the latest browsers.

like image 168
markE Avatar answered Sep 29 '22 04:09

markE


The canvas image needs to be converted to base64 and then from base64 in to binary. This is done using .toDataURL() and dataURItoBlob()

It was a pretty fiddly process which required piecing together several SO answers, various blog posts and tutorials.

I've created a tutorial you can follow which walks you through the process.

In response to Ateik's comment here's a fiddle which replicates the original post in case you're having trouble viewing the original link. You can also fork my project here.

There's a lot of code but the core of what I'm doing is take a canvas element:

<canvas id="flatten" width="800" height="600"></canvas> 

Set it's context to 2D

var snap = document.getElementById('flatten'); var flatten = snap.getContext('2d'); 

Canvas => Base64 => Binary

function postCanvasToURL() {    // Convert canvas image to Base64    var img = snap.toDataURL();    // Convert Base64 image to binary    var file = dataURItoBlob(img);  }    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});  }

You could stop at base64 if that's all you need, in my case I needed to convert again to binary so that I could pass the data over to twitter (using OAuth) without use of a db. It turns out you can tweet binary which is pretty cool, twitter will convert it back in to an image.

like image 23
Pixelomo Avatar answered Sep 29 '22 05:09

Pixelomo