J'utilise l'outil JavaScript "Canvas2Image" de Nihilogic pour convertir les dessins sur toile en images PNG. Ce que j'ai maintenant besoin, c’est de convertir les chaînes base64 générées par cet outil en fichiers PNG réels sur le serveur, à l’aide de PHP.
En bref, je suis en train de générer un fichier côté client à l'aide de Canvas2Image, puis de récupérer les données codées en base64 et de les envoyer au serveur à l'aide d'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
}
});
À ce stade, "hidden.php" reçoit un bloc de données ressemblant àdata: image/png; base64, iVBORw0KggoAAAANSUhEUgAABE ...
À partir de ce moment, je suis assez perplexe. D'après ce que j'ai lu, je suis supposé utiliser la fonction imagecreatefromstring de PHP, mais je ne sais pas comment créer une image PNG réelle à partir de la chaîne encodée en base64 et la stocker sur mon serveur. . S'il vous plaît aider!
Vous devez extraire les données d'image base64 de cette chaîne, les décoder et les sauvegarder sur disque, vous n'avez pas besoin de Gd car il s'agit déjà d'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);
Et comme une ligne:
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $data));
Une méthode efficace pour extraire, décoder et vérifier les erreurs est la suivante:
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);
J'ai dû remplacer les espaces par les symboles plus str_replace(' ', '+', $img);
pour que cela fonctionne.
Voici le code complet
$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);
J'espère que cela pourra aider.
Cela vaut la peine de dire que le sujet discuté est documenté dans RFC 2397 - Le schéma d'URL "data" ( https://tools.ietf.org/html/rfc2397 )
A cause de cela PHP a un moyen natif de gérer de telles données - "data: stream wrapper" ( http://php.net/manual/en/wrappers.data.php )
Ainsi, vous pouvez facilement manipuler vos données avec PHP streams:
$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);
Suivant l’idée de @ dre010, je l’ai étendue à une autre fonction qui fonctionne avec n’importe quel type d’image: PNG, JPG, JPEG ou GIF et donne un nom unique au nom de fichier
La fonction sépare les données d'image et le type d'image
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);
}
Votre solution ci-dessus dépend de l’image étant un fichier jpeg. Pour une solution générale j'ai utilisé
$img = $_POST['image'];
$img = substr(explode(";",$img)[1], 7);
file_put_contents('img.png', base64_decode($img));
Total des préoccupations:
$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);
}
Une solution linéaire.
$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]));
essaye ça...
$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));
Ce code fonctionne pour moi vérifier le code ci-dessous:
<?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);
?>
sur la base de l'exemple drew010, j'ai créé un exemple pratique pour faciliter la compréhension.
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;
}
Cette fonction devrait fonctionner. cela a le paramètre photo qui contient la chaîne base64 et le chemin d'accès à un répertoire d'image existant si vous avez déjà une image existante que vous souhaitez dissocier pendant la sauvegarde de la nouvelle.
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
}
}
}
C'est simple :
Imaginons que vous essayiez de télécharger un fichier dans le framework js, une requête ajax ou une application mobile (côté client)
Voici comment faire en utilisant PHP
<?php
$base64String = "kfezyufgzefhzefjizjfzfzefzefhuze"; // I put a static base64 string, you can implement you special code to retrieve the data received via the request.
$filePath = "/MyProject/public/uploads/img/test.png";
file_put_contents($filePath, base64_decode($base64String));
?>