Cum salvezi o imagine cu link base64 fără a folosi download atributte

Cum salvezi o imagine cu link base64 fără a folosi download attribute

Recitind titlul îmi dau seama că de multe ori mi-e greu să-mi înțeleg propriile propoziții. Dar cine va avea răbdarea să citească acest articol, va înțelege de unde limbajul de lemn și împrăștiat.

Situație: Am avut de făcut o aplicație de genul acela în care un utilizator își poate introduce o poză portret într-un template deja realizat, să zicem o secvență dintr-un desenat animat. Astfel, rezultatul final al procesului este un colaj cu fața utilizatorului în acea secvență, în format png.

Salvatul imaginii se făceau cu un simplu a href, care ducea către un link png de tip base64 (prin urmare, dinamic), cu un download attribute în interior. Guess what? Internet Explorer și Edge nu recunosc acel download attribute! Ba mai mult, la un click pe acel link/button, dacă aveai un sistem mai slab, exista o maaaare probabilitate ca browserul să crape.

Cum am procedat astfel încât să creez o alternativă la acel tip de link?

Pentru cei ce nu știu cum arată un link de care am pomenit mai sus, iată un exemplu:

<img src="data:image/png;base64,iVBORw0KGgodsdsAAAANSUhEUgAAAdsdsCAAAAAgCAMAAABEpIrGAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAU1QTFRFNjtAQEVK////bG9zSk9T/v7+/f39/f3+9vf3O0BETlJWNzxB/Pz8d3t+TFFVzM3O1NXX7u/vUldbRElNs7W3v8HCmZyeRkpPW19j8vLy7u7vvsDC9PT1cHR3Oj9Eo6WnxsjJR0tQOD1Bj5KVgYSHTVFWtri50dLUtLa4YmZqOT5D8vPzRUpOkZOWc3Z64uPjr7Gzuru95+C" />

Bun, am lămurit și asta. Deci, care-i alternativa la acel atribut în link? Niciuna! Yep… Edge, Internet Explorer și ulterior am aflat că nici Safari, nu reușesc să înțeleagă în mărinimia lor acel atribut.

Așa că după documentare, dialoguri pe Stackoverflow desprinse nu tocmai din politețea Poienii lui Iocan, am aflat că există posibilitatea să creez un canvas, în care sa afișez png-ul și cumva să pot salva conținutul acelui canvas. Pentru asta trebuia să folosesc FileSaver.js și canvas-toBlob.js.  Mare atenție la instalarea lui FileSaver.js prin npm, veți primi ceva eroare cum că nu poate fi instalat modulul ca „own dependecy” sau ceva de genul ăsta. Așa, că intrați în fișierul JSON și schimbați numele proiectului din file-saver, în file-saver.2, de exemplu, iar instalarea va rula fără probleme.

Instrucțiuni și cod pentru a rezolva problema.

Prima și prima dată se include cele două fișiere JS în header, după ce sunt instalate.  Încă o dată, vreau sa menționez că folosirea lui FileSaver.js din arhiva de pe GitHub nu va funcționa, pentru că acela e doar un demo. Trebuie instalată toata suita de chestii folosind instalarea prin npm. Și nu cred că mai are rost să spun că trebuie instalată și o librărie cât de cât actuală de jQuery, de exemplu.. de la Google.

Se dă această imagine:

<img border="0" src="<?php echo $_POST['img_val']; ?>" alt="" width="800" height="auto" id="my-canvas" style="display:none;">

Vedeți că i-am dat un display:none, asta pentru a nu avea afișată imaginea de două ori în pagină. Neapărat, trebuie introdusă imaginea înainte de canvas, altfel, acesta nu va ști ce să „deseneze”.

Bun, prima dată creăm canvasul:

<canvas id="SuperCanvas" width="802" height="640" ></canvas>

I-am dat, practic, dimensiunile pngului pe care dorim să îl exportăm. După ce am creat canvasul, trebuie să desenăm conținutul în el, adică imaginea noastra finală, colajul. Calea către imagine este generată dinamic de către o funcție php.

var canvas = document.getElementById('SuperCanvas'),
canvas.getContext('2d');

make_base();

function make_base()
{
  base_image = new Image();
  base_image.src = '<?php echo $_POST['img_val']; ?>';
  base_image.onload = function(){
    context.drawImage(base_image, 0, 0);
  }
}

Apoi salvăm pngul:


var canvas = document.getElementById("SuperCanvas"), ctx = canvas.getContext("2d");
// draw to canvas...
canvas.toBlob(function(blob) {
    saveAs(blob, "nume-imagine.png");
});

Atenție! Această funcție va descărca automat acel png. Iar de cele mai multe ori png-ul va fi gol, pentru că nu pagina nu va avea timp să preia informația din canvas. Așa că cel mai bine facem o funcție și o atașăm unui buton de descărcare.
Creăm funcția necesară salvării pngului:

function canvas2Image() {
var canvas = document.getElementById("SuperCanvas"), ctx = canvas.getContext("2d");
// draw to canvas...
canvas.toBlob(function(blob) {
    saveAs(blob, "nume-imagine.png");
});
}

Apoi punem un buton:

<input type="button" value="Descarca" onclick="canvas2Image();"/>

Și cam asta e! 🙂

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *