ChatGPT解决这个技术问题 Extra ChatGPT

如何从 base64 数据 URI 保存 PNG 图像服务器端

我正在使用 Nihilogic 的“Canvas2Image”JavaScript 工具将画布绘图转换为 PNG 图像。我现在需要的是使用 PHP 将这个工具生成的那些 base64 字符串转换为服务器上的实际 PNG 文件。

简而言之,我目前正在做的是使用 Canvas2Image 在客户端生成一个文件,然后检索 base64 编码的数据并使用 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
    }
});

此时,“hidden.php”收到一个数据块,看起来像 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABE...

从这一点开始,我几乎被难住了。根据我的阅读,我相信我应该使用 PHP 的 imagecreatefromstring 函数,但我不确定如何从 base64 编码的字符串实际创建一个实际的 PNG 图像并将其存储在我的服务器上。请帮忙!

你需要解析它。您可以从那里提取图像类型,然后使用 base64_decode 并将该字符串按您的图像类型保存在文件中
@Constantine 你能更具体一点吗?
$data = $_REQUEST['base64data']; $image = explode('base64,',$data); file_put_contents('img.png', base64_decode($image[1]));
你可以发布完整的代码,从快照到你发送数据,它对我不起作用。

C
Community

您需要从该字符串中提取 base64 图像数据,对其进行解码,然后将其保存到磁盘,您不需要 GD,因为它已经是 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);

作为单线:

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

提取、解码和检查错误的有效方法是:

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 = str_replace( ' ', '+', $data );
    $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);

您的示例中有 $type 。这个值应该是多少?
@Jon $type 从爆炸中获得一个值,具体取决于它是 data:image/jpg 还是 data:image/png 等。
我收到此错误:格式错误的 utf-8 字符可能编码不正确我该怎么办?
@aldo 可能会发布一个包含代码和详细信息的新问题。仅基于该消息并且不查看您的代码或不知道图像是如何编码以及它是如何发送到脚本的,几乎不可能说出来。
我猜 $type 不适用于 .svg 文件,mimetype:image/svg+xml
S
Some Guy

尝试这个:

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

file_put_contents docs


我试过这个,但它包括破坏文件的 data:image/png;base64,
@MichaelCalkins 也为我打破了它。 draw010 的答案似乎是唯一有效的解决方案。
如果您包含 data:image/png;base64,,那么您传递给 base64_decode 的字符串不是有效的 base64。您只需要发送数据,这就是 draw010 的答案所说明的。这个答案没有任何问题。您不能在不理解的情况下复制和粘贴并期望它“正常工作”。
不适用于问题中提供的示例,它不是 base64 内容,首先必须分成几部分(请参阅接受的答案)。
我的图像已成功保存。但是当我写图像的网址时,我看到一个空白图像。我确信我的 dataURL 是正确的,因为我使用 window.open(dataURL) 进行了测试。为什么是空白图像?
B
Ben

我必须用加号 str_replace(' ', '+', $img); 替换空格才能使其正常工作。

这是完整的代码

$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);

希望有帮助。


您的线路 $img = str_replace(' ', '+', $img); 对我帮助很大,谢谢!为什么我必须先将空格转换为“+”?
是否需要以某种方式验证这些数据?就像您通常使用 $_FILES 数据一样?如果是这样,那怎么可能
C
Community

值得一提的是,讨论的主题记录在 RFC 2397 - “数据” URL 方案 (https://www.rfc-editor.org/rfc/rfc2397)

因此,PHP 有一种处理此类数据的本机方式 - “数据:流包装器”(http://php.net/manual/en/wrappers.data.php

因此,您可以使用 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);

我喜欢这个答案,它应该有更多的投票,它使用本机函数,没有肮脏的自制数据操作!虽然,关于表演的任何想法?正如人们所预料的那样,它是否比 preg_replace + file_put_contents 更快?
@Bonswoar 谢谢。关于您的问题:在我看来,确保您的应用程序没有性能问题的最佳方法是在您的特定情况下测量其性能(基于环境、预期和允许的文件大小等)。我们可以尝试在此处使用代码并在答案中显示数字,但事实是,对于您的确切情况,它可能带来的伤害多于积极的结果。最好自己确定(尤其是在我们谈论应用程序的性能关键部分时)。
P
PolloZen

采用@dre010 的想法,我将其扩展为适用于任何图像类型的另一个函数:PNG、JPG、JPEG 或 GIF,并为文件名提供唯一名称

功能分离图像数据和图像类型

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);
}

d
devil_io

那么您上面的解决方案取决于图像是 jpeg 文件。对于我使用的一般解决方案

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

G
Greg Schmidt

总的担忧:

$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


P
Piotr

单线性解。

$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]));

G
Gauravbhai Daxini

此代码适用于我检查以下代码:

<?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);
?>

s
sanjeet bisht

基于draw010示例,我制作了一个工作示例以便于理解。

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; 
}

P
Paline

尝试这个...

$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));

P
PYK

PHP 已经公平对待 base64 -> 文件转换

我用这种方式完成编码:

$blob=$_POST['blob']; // base64 coming from an url, for example

//Now, let's save the image file:

file_put_contents('myfile.png',file_get_contents($blob));

这应该是公认的答案,因为 OP 将 base64 字符串格式化为 URL,以 data:image/png;base64, 开头。
h
hisablik

假设您在 $filename 中有文件名,在 $testfile 我的 oneliner 中有 base64encoded 字符串:

file_put_contents($filename,base64_decode(explode(',', $testfile)[1]))


S
Saviour Dela

这个功能应该可以工作。这具有保存 base64 字符串的 photo 参数以及现有图像目录的路径,如果您已经拥有要在保存新图像时取消链接的现有图像。

 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
        }
    }
}

M
Mustapha GHLISSI

这很简单 :

假设您正在尝试在 js 框架、ajax 请求或移动应用程序(客户端)中上传文件

首先,您发送一个包含 base64 编码字符串的数据属性。在服务器端,您必须对其进行解码并将其保存在本地项目文件夹中。

在这里如何使用 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));

?>

C
Community

如果您想随机重命名图像,并将数据库上的图像路径存储为 blob 并将图像本身存储在文件夹中,此解决方案将为您提供帮助。您的网站用户可以存储任意数量的图像,而出于安全目的,图像将被随机重命名。

php代码

生成随机 varchars 以用作图像名称。

function genhash($strlen) {
        $h_len = $len;
        $cstrong = TRUE;
        $sslkey = openssl_random_pseudo_bytes($h_len, $cstrong);
        return bin2hex($sslkey);
}
$randName = genhash(3); 
#You can increase or decrease length of the image name (1, 2, 3 or more).

从 image 获取图像数据扩展名和 base_64 部分(data:image/png;base64, 之后的部分)。

$pos  = strpos($base64_img, ';');
$imgExten = explode('/', substr($base64_img, 0, $pos))[1];
$extens = ['jpg', 'jpe', 'jpeg', 'jfif', 'png', 'bmp', 'dib', 'gif' ];

if(in_array($imgExten, $extens)) {

   $imgNewName = $randName. '.' . $imgExten;
   $filepath = "resources/images/govdoc/".$imgNewName;
   $fileP = fopen($filepath, 'wb');
   $imgCont = explode(',', $base64_img);
   fwrite($fileP, base64_decode($imgCont[1]));
   fclose($fileP);

}

# => $filepath <= This path will be stored as blob type in database.
# base64_decoded images will be written in folder too.

# Please don't forget to up vote if you like my solution. :)