Convertire la canvas HTML5 nel file da caricare?

Il caricamento di file HTML standard funziona come segue:

   

Nel mio caso ho caricato un’immagine in una canvas html5 e desidero inviarla come file al server. Posso fare:

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

Questo mi dà un’immagine / png come base64.

Come posso inviare l’immagine base64 al server nello stesso modo in cui viene eseguita con il file del tipo di input?

Il problema è che il file base64 non è dello stesso tipo del file, che è all’interno del tipo di input = “file”.

Posso convertire il base64 che i tipi sono gli stessi per il server in qualche modo?

Per motivi di sicurezza, non è ansible impostare direttamente il valore di un elemento di input del file.

Se si desidera utilizzare un elemento di input del file:

  1. Crea un’immagine dalla canvas (come hai fatto tu).
  2. Mostra quell’immagine su una nuova pagina.
  3. Chiedere all’utente di fare clic con il pulsante destro del mouse su Salva come unità locale.
  4. Quindi possono usare l’elemento di input del file per caricare il file appena creato.

In alternativa, puoi usare Ajax per POST i dati del canvas:

Hai chiesto informazioni su 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); }); 

Nota: BLOB è generalmente supportato negli ultimi browser.

L’immagine della canvas deve essere convertita in base64 e quindi da base64 in binario. Questo viene fatto usando .toDataURL() e dataURItoBlob()

È stato un processo abbastanza complesso che ha richiesto di mettere insieme diverse risposte SO, vari post del blog ed esercitazioni.

Ho creato un tutorial da seguire che ti guida attraverso il processo .

In risposta al commento di Ateik, ecco un violino che replica il post originale nel caso in cui abbia difficoltà a visualizzare il link originale. Puoi anche inserire il mio progetto qui .

C’è molto codice ma il nucleo di ciò che sto facendo è prendere un elemento di canvas:

  

Imposta il suo contesto in 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}); } 

Un’altra soluzione: inviare i dati in var url in un campo nascosto, decodificarli e salvarli sul server.

Esempio in Python Django:

 if form.is_valid(): url = form.cleaned_data['url'] url_decoded = b64decode(url.encode()) content = ContentFile(url_decoded) your_model.model_field.save('image.png', content) 

Attualmente nelle specifiche (pochissimo supporto a partire da aprile ’17)

Canvas.toBlob();

https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob

MODIFICARE :

Il link fornisce un polyfill (che sembra essere più lento dal testo), il cui codice è equivalente in modo rudimentale alla risposta @pixelomo, ma con la stessa api del metodo nativo toBlob :

Un polyfill a prestazioni ridotte basato su toDataURL:

 if (!HTMLCanvasElement.prototype.toBlob) { Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', { value: function (callback, type, quality) { var canvas = this; setTimeout(function() { var binStr = atob( canvas.toDataURL(type, quality).split(',')[1] ), len = binStr.length, arr = new Uint8Array(len); for (var i = 0; i < len; i++ ) { arr[i] = binStr.charCodeAt(i); } callback( new Blob( [arr], {type: type || 'image/png'} ) ); }); } }); } 

Per essere usato in questo modo:

 canvas.toBlob(function(blob){...}, 'image/jpeg', 0.95); // JPEG at 95% quality 

o

 canvas.toBlob(function(blob){...}); // PNG