Come salvare un’immagine PNG lato server, da una stringa di dati base64

Sto usando lo strumento JavaScript “Canvas2Image” di Nihilogic per convertire i disegni su canvas in immagini PNG. Quello di cui ho bisogno ora è di trasformare quelle stringhe base64 che questo strumento genera, in file PNG reali sul server, usando PHP.

In breve, quello che sto facendo è generare un file sul lato client usando Canvas2Image, quindi recuperare i dati codificati in base64 e inviarlo al server usando AJAX:

// Generate the image file var image = Canvas2Image.saveAsPNG(canvas, true); image.id = "canvasimage"; canvas.parentNode.replaceChild(image, canvas); var url = 'hidden.php', data = $('#canvasimage').attr('src'); $.ajax({ type: "POST", url: url, dataType: 'text', data: { base64data : data } }); 

A questo punto, “hidden.php” riceve un blocco dati che assomiglia a dati: image / png; base64, iVBORw0KGgoAAAANSUhEUgAABE …

Da questo punto in poi, sono abbastanza perplesso. Da quello che ho letto, credo che dovrei usare la funzione imagecreatefromstring di PHP, ma non sono sicuro di come effettivamente creare un’immagine PNG reale dalla stringa codificata in base64 e memorizzarla sul mio server. Per favore aiuto!

È necessario estrarre i dati dell’immagine base64 da quella stringa, decodificarla e quindi salvarla su disco, non è necessario GD poiché è già un png.

 $data = 'data:image/png;base64,AAAFBfj42Pj4'; list($type, $data) = explode(';', $data); list(, $data) = explode(',', $data); $data = base64_decode($data); file_put_contents('/tmp/image.png', $data); 

E come one-liner:

 $data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $data)); 

Un metodo efficiente per l’estrazione, la decodifica e il controllo degli errori è:

 if (preg_match('/^data:image\/(\w+);base64,/', $data, $type)) { $data = substr($data, strpos($data, ',') + 1); $type = strtolower($type[1]); // jpg, png, gif if (!in_array($type, [ 'jpg', 'jpeg', 'gif', 'png' ])) { throw new \Exception('invalid image type'); } $data = base64_decode($data); if ($data === false) { throw new \Exception('base64_decode failed'); } } else { throw new \Exception('did not match data URI with image data'); } file_put_contents("img.{$type}", $data); 

Prova questo:

 file_put_contents('img.png', base64_decode($base64string)); 

file_put_contents docs

Ho dovuto sostituire gli spazi con i simboli plus str_replace(' ', '+', $img); per farlo funzionare.

Ecco il codice completo

 $img = $_POST['img']; // Your data 'data:image/png;base64,AAAFBfj42Pj4'; $img = str_replace('data:image/png;base64,', '', $img); $img = str_replace(' ', '+', $img); $data = base64_decode($img); file_put_contents('/tmp/image.png', $data); 

Spero possa aiutare.

Vale la pena di dire che l’argomento discusso è documentato in RFC 2397 – Lo schema di URL “dati” ( https://tools.ietf.org/html/rfc2397 )

Per questo motivo PHP ha un modo nativo per gestire tali dati: “data: stream wrapper” ( http://php.net/manual/en/wrappers.data.php )

In questo modo puoi facilmente manipolare i tuoi dati con stream PHP:

 $data = 'data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7'; $source = fopen($data, 'r'); $destination = fopen('image.gif', 'w'); stream_copy_to_stream($source, $destination); fclose($source); fclose($destination); 

Bene, la soluzione sopra dipende dall’immagine come file jpeg. Per una soluzione generale che ho usato

 $img = $_POST['image']; $img = substr(explode(";",$img)[1], 7); file_put_contents('img.png', base64_decode($img)); 

Presa l’idea @ dre010, l’ho estesa ad un’altra funzione che funziona con qualsiasi tipo di immagine: PNG, JPG, JPEG o GIF e dà un nome univoco al nome del file

La funzione separa i dati dell’immagine e il tipo di immagine

 function base64ToImage($imageData){ $data = 'data:image/png;base64,AAAFBfj42Pj4'; list($type, $imageData) = explode(';', $imageData); list(,$extension) = explode('/',$type); list(,$imageData) = explode(',', $imageData); $fileName = uniqid().'.'.$extension; $imageData = base64_decode($imageData); file_put_contents($fileName, $imageData); } 

prova questo…

 $file = $_POST['file']; //your data in base64 'data:image/png....'; $img = str_replace('data:image/png;base64,', '', $file); file_put_contents('img/imag.png', base64_decode($img)); 

Soluzione lineare.

 $base64string = 'data:image/png;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7'; file_put_contents('img.png', base64_decode(explode(',',$base64string)[1])); 

Questo codice funziona per me controllare il seguente codice:

 < ?php define('UPLOAD_DIR', 'images/'); $image_parts = explode(";base64,", $_POST['image']); $image_type_aux = explode("image/", $image_parts[0]); $image_type = $image_type_aux[1]; $image_base64 = base64_decode($image_parts[1]); $file = UPLOAD_DIR . uniqid() . '.png'; file_put_contents($file, $image_base64); ?> 

Preoccupazioni totali:

 $data = 'data:image/png;base64,AAAFBfj42Pj4'; // Extract base64 file for standard data $fileBin = file_get_contents($data); $mimeType = mime_content_type($data); // Check allowed mime type if ('image/png'==$mimeType) { file_put_contents('name.png', $fileBin); } 

http://php.net/manual/en/wrappers.data.php

http://php.net/manual/en/function.mime-content-type.php

sulla base dell’esempio drew010 ho fatto un esempio funzionante per una facile comprensione.

 imagesaver("data:image/jpeg;base64,/9j/4AAQSkZJ"); //use full base64 data function imagesaver($image_data){ list($type, $data) = explode(';', $image_data); // exploding data for later checking and validating if (preg_match('/^data:image\/(\w+);base64,/', $image_data, $type)) { $data = substr($data, strpos($data, ',') + 1); $type = strtolower($type[1]); // jpg, png, gif if (!in_array($type, [ 'jpg', 'jpeg', 'gif', 'png' ])) { throw new \Exception('invalid image type'); } $data = base64_decode($data); if ($data === false) { throw new \Exception('base64_decode failed'); } } else { throw new \Exception('did not match data URI with image data'); } $fullname = time().$type; if(file_put_contents($fullname, $data)){ $result = $fullname; }else{ $result = "error"; } /* it will return image name if image is saved successfully or it will return error on failing to save image. */ return $result; } 

Questa funzione dovrebbe funzionare. questo ha il parametro foto che contiene la stringa base64 e anche il percorso di una directory immagine esistente se si dispone già di un’immagine esistente che si desidera scolbind mentre si salva quella nuova.

  public function convertBase64ToImage($photo = null, $path = null) { if (!empty($photo)) { $photo = str_replace('data:image/png;base64,', '', $photo); $photo = str_replace(' ', '+', $photo); $photo = str_replace('data:image/jpeg;base64,', '', $photo); $photo = str_replace('data:image/gif;base64,', '', $photo); $entry = base64_decode($photo); $image = imagecreatefromstring($entry); $fileName = time() . ".jpeg"; $directory = "uploads/customer/" . $fileName; header('Content-type:image/jpeg'); if (!empty($path)) { if (file_exists($path)) { unlink($path); } } $saveImage = imagejpeg($image, $directory); imagedestroy($image); if ($saveImage) { return $fileName; } else { return false; // image not saved } } }