关于php:如何从base64数据字符串保存PNG图像服务器端

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
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $data));

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

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
file_put_contents('img.png', base64_decode($base64string));

文件放目录文档


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

这是完整的代码

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请求或移动应用程序(客户端)中上载文件。

  • 首先,发送一个包含base64编码的数据属性字符串。
  • 在服务器端,您必须将其解码并保存到本地项目文件夹。
  • 下面介绍如何使用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
            }
        }
    }