How to save a PNG image server-side, from a base64 data string
我正在使用nihilogic的"canvas2image"javascript工具将画布绘图转换为PNG图像。我现在需要的是使用PHP将这个工具生成的base64字符串转换成服务器上的实际PNG文件。
简而言之,我目前正在做的是使用canvas2image在客户端生成一个文件,然后检索base64编码的数据,并使用ajax将其发送到服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 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 } }); |
此时,"hidden.php"接收一个看起来像数据的数据块:image/png;base64,ivborw0kgoaaaansuheugaabe…
从这一点上说,我几乎被难住了。据我所读,我相信我应该使用php的imagecreatefromstring函数,但我不知道如何从base64编码的字符串实际创建一个PNG图像并将其存储在我的服务器上。请帮帮我!
您需要从该字符串中提取base64图像数据,对其进行解码,然后将其保存到磁盘,您不需要gd,因为它已经是一个png。
1 2 3 4 5 6 7 | $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); |
作为一条直线:
1 |
提取、解码和检查错误的有效方法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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); |
试试这个:
1 |
文件放目录文档
我必须用加号
这是完整的代码
1 2 3 4 5 | $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); |
希望有帮助。
值得一提的是,讨论的主题记录在RFC2397"数据"URL方案(https://tools.ietf.org/html/rfc2397)中。
因此,PHP具有处理此类数据的本机方式-"data:stream wrapper"(http://php.net/manual/en/wrappers.data.php)
因此,您可以使用PHP流轻松地操作数据:
1 2 3 4 5 6 7 8 9 | $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); |
采用@dre010的思想,我将它扩展到了另一个可以处理任何图像类型的函数:png、jpg、jpeg或gif,并为文件名提供了唯一的名称。
功能将图像数据和图像类型分开
1 2 3 4 5 6 7 8 9 | 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); } |
那么,上面的解决方案取决于图像是一个jpeg文件。对于我使用的一般解决方案
1 2 3 | $img = $_POST['image']; $img = substr(explode(";",$img)[1], 7); file_put_contents('img.png', base64_decode($img)); |
总关注点:
1 2 3 4 5 6 7 8 9 10 | $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
一个线性解。
1 2 | $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])); |
基于drew010的例子,我做了一个很好的例子以便于理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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; } |
此代码适用于我。请检查以下代码:
1 2 3 4 5 6 7 8 9 | <?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); ?> |
试试这个…
1 2 3 | $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)); |
很简单:
假设您正在尝试在JS框架、Ajax请求或移动应用程序(客户端)中上载文件。
下面介绍如何使用PHP
1 2 3 4 5 6 7 8 9 | <?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)); ?> |
这个功能应该可以工作。它有一个photo参数,该参数保存base64字符串,如果在保存新图像时已有一个要取消链接的现有图像,则还包含到现有图像目录的路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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 } } } |