Cách lưu phía máy chủ hình ảnh PNG, từ chuỗi dữ liệu base64


212

Tôi đang sử dụng công cụ JavaScript "Canvas2Image" của Nihilogic để chuyển đổi các bản vẽ canvas thành hình ảnh PNG. Điều tôi cần bây giờ là biến những chuỗi cơ sở64 mà công cụ này tạo ra, thành các tệp PNG thực trên máy chủ, sử dụng PHP.

Nói tóm lại, những gì tôi hiện đang làm là tạo một tệp ở phía máy khách bằng Canvas2Image, sau đó lấy dữ liệu được mã hóa base64 và gửi nó đến máy chủ bằng 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
    }
});

Tại thời điểm này, "hidden.php" nhận được một khối dữ liệu trông giống như dữ liệu: image / png; base64, iVBORw0KGgoAAAANSUhEUgAABE ...

Từ thời điểm này, tôi khá bối rối. Từ những gì tôi đã đọc, tôi tin rằng tôi nên sử dụng hàm chuỗi ký tự tưởng tượng của PHP , nhưng tôi không chắc chắn làm thế nào để thực sự tạo ra một hình ảnh PNG thực tế từ chuỗi được mã hóa base64 và lưu trữ nó trên máy chủ của tôi. Xin hãy giúp đỡ!


bạn cần phân tích nó bạn có thể trích xuất loại hình ảnh từ đó và sau đó sử dụng base64_decode và lưu chuỗi đó trong một tệp theo loại hình ảnh của bạn
Constantin

@Constantine Bạn có thể cụ thể hơn được không?
Andrei Oniga

7
$ data = $ _REQUEST ['base64data']; $ image = explode ('base64,', $ data); file_put_contents ('img.png', base64_decode ($ image [1]));
Constantin

bạn có thể đăng mã đầy đủ, từ ảnh chụp nhanh và cho đến khi bạn gửi dữ liệu, nó không hoạt động đối với tôi.
Ofir Attia

Câu trả lời:


437

Bạn cần trích xuất dữ liệu hình ảnh base64 từ chuỗi đó, giải mã nó và sau đó bạn có thể lưu nó vào đĩa, bạn không cần GD vì nó đã là 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);

Và như một lớp lót:

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

Một phương pháp hiệu quả để trích xuất, giải mã và kiểm tra lỗi là:

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

Bạn có loại $ trong ví dụ của bạn. Giá trị đó nên là gì?
Jon

1
@Jon $typeđược gán một giá trị từ vụ nổ, tùy thuộc vào dữ liệu đó là: hình ảnh / jpg hoặc dữ liệu: hình ảnh / png, v.v.
drew010

tôi đã gặp lỗi này: các ký tự utf-8 không đúng có thể được mã hóa sai, tôi nên làm gì?
aldo

@aldo Có lẽ gửi một câu hỏi mới với mã và chi tiết. Khá khó để nói chỉ dựa trên tin nhắn đó và không nhìn thấy mã của bạn hoặc biết cách hình ảnh được mã hóa và cách nó được gửi đến tập lệnh.
rút ra

120

Thử cái này:

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

file_put_contents docs


4
Tôi đã thử điều này nhưng nó bao gồm cả việc data:image/png;base64,phá vỡ tập tin.
Michael J. Calkins

2
@MichaelCalkins Phá vỡ nó cho tôi, quá. Câu trả lời của drew010 dường như là giải pháp duy nhất hoạt động ổn định.
David John Welsh

24
Nếu bạn bao gồm data:image/png;base64,chuỗi thì chuỗi bạn chuyển đến base64_decodekhông hợp lệ64. Bạn chỉ cần gửi dữ liệu, đó là câu trả lời của drew010 đang minh họa. Không có gì bị phá vỡ với câu trả lời này. Bạn không thể sao chép và dán mà không hiểu và mong đợi nó "chỉ hoạt động".
Cypher

4
Không hoạt động cho ví dụ được cung cấp trong câu hỏi, không phải là nội dung cơ sở64 và trước tiên phải được chia thành từng phần (xem câu trả lời được chấp nhận).
Benjamin Piette

hình ảnh của tôi đã được lưu thành công. nhưng khi tôi viết url của hình ảnh tôi thấy một hình ảnh trống. Tôi chắc chắn rằng dataURL của tôi là chính xác, vì tôi đã kiểm tra rằng sử dụng window.open (dataURL). Tại sao một hình ảnh trống?
partho

45

Tôi đã phải thay thế không gian bằng các biểu tượng cộng str_replace(' ', '+', $img);để làm việc này.

Đây là mã đầy đủ

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

Mong rằng sẽ giúp.


1
Dòng của bạn $img = str_replace(' ', '+', $img);đã giúp tôi rất nhiều, cảm ơn! Tại sao tôi phải chuyển đổi không gian thành "+" trước đó?
Sven

19

Điều đáng nói là chủ đề thảo luận được ghi lại trong RFC 2397 - Lược đồ URL "dữ liệu" ( https://tools.ietf.org/html/rfc2394 )

Bởi vì PHP này có một cách riêng để xử lý dữ liệu đó - "data: stream Wrapper" ( http://php.net/manual/en/wrappers.data.php )

Vì vậy, bạn có thể dễ dàng thao tác dữ liệu của mình với các luồng 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);

2
Tôi thích câu trả lời này, nó nên có nhiều phiếu bầu hơn, nó sử dụng các hàm riêng, không có thao tác dữ liệu tự chế bẩn! Mặc dù, bất kỳ ý tưởng về màn trình diễn? Là nó, như người ta có thể mong đợi, nhanh hơn preg_replace+ file_put_contents?
Bonswouar

1
@Bonswouar Cảm ơn. Về câu hỏi của bạn: theo tôi, cách tốt nhất để đảm bảo rằng ứng dụng của bạn không gặp vấn đề về hiệu năng sẽ là đo hiệu năng của nó trong trường hợp cụ thể của bạn (dựa trên môi trường, kích thước tệp dự kiến ​​và được phép, v.v.). Chúng tôi có thể thử chơi mã ở đây và hiển thị số trong câu trả lời, nhưng sự thật là đối với trường hợp chính xác của bạn, nó có thể mang lại nhiều tác hại hơn là kết quả tích cực. Luôn luôn tốt hơn để đảm bảo một mình (đặc biệt nếu chúng ta đang nói về các phần quan trọng về hiệu năng của ứng dụng).
Vladimir Posvistelik

11

Vâng, giải pháp của bạn ở trên phụ thuộc vào hình ảnh là một tệp jpeg. Đối với một giải pháp chung tôi đã sử dụng

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

11

Lấy ý tưởng @ dre010, tôi đã mở rộng nó sang một chức năng khác hoạt động với mọi loại hình ảnh: PNG, JPG, JPEG hoặc GIF và đặt một tên duy nhất cho tên tệp

Chức năng tách dữ liệu hình ảnh và loại hình ảnh

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


5

Giải pháp một tuyến tính.

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

5

dựa trên ví dụ drew010 tôi đã làm một ví dụ làm việc để dễ hiểu.

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

4

thử cái này...

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

4

Mã này hoạt động cho tôi kiểm tra mã dưới đây:

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

0

Chức năng này sẽ hoạt động. cái này có tham số ảnh chứa chuỗi base64 và cũng đường dẫn đến thư mục hình ảnh hiện có nếu bạn đã có một hình ảnh hiện có mà bạn muốn hủy liên kết trong khi bạn lưu cái mới.

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

0

Thật đơn giản:

Hãy tưởng tượng rằng bạn đang cố tải lên một tệp trong khung js, yêu cầu ajax hoặc ứng dụng di động (Phía khách hàng)

  1. Đầu tiên bạn gửi một thuộc tính dữ liệu có chứa chuỗi được mã hóa base64.
  2. Ở phía máy chủ, bạn phải giải mã nó và lưu nó vào một thư mục dự án cục bộ.

Dưới đây là cách thực hiện bằng 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));

?>

0

Nếu bạn muốn đổi tên ngẫu nhiên hình ảnh và lưu trữ cả đường dẫn hình ảnh trên cơ sở dữ liệu dưới dạng blob và hình ảnh trên các thư mục, giải pháp này sẽ giúp bạn. Người dùng trang web của bạn có thể lưu trữ nhiều hình ảnh như họ muốn trong khi hình ảnh sẽ được đổi tên ngẫu nhiên cho mục đích bảo mật.

Mã php

Tạo varchars ngẫu nhiên để sử dụng làm tên hình ảnh.

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).

Nhận phần mở rộng dữ liệu hình ảnh và phần base_64 (phần sau dữ liệu: image / png; base64,) từ hình ảnh.

$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. :)

0

PHP đã đối xử công bằng bằng64 -> chuyển đổi tệp

Tôi sử dụng để hoàn thành nó theo cách này:

$blob=$_POST['blob']; // base64 coming from an url, for example
$blob=file_get_contents($blob);
$fh=fopen("myfile.png",'w'); // be aware, it'll overwrite!
fwrite($fh,$blob);
fclose($fh);
echo '<img src=myfile.png>'; // just for the check
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.