base64 데이터 문자열에서 PNG 이미지 서버 측을 저장하는 방법


212

캔버스 그림을 PNG 이미지로 변환하기 위해 Nihilogic의 "Canvas2Image"JavaScript 도구를 사용하고 있습니다. 내가 지금 필요한 것은 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를 사용하여 이미지 유형별로 파일에 해당 문자열을 저장할 수 있습니다
Constantin

@Constantine 좀 더 구체적으로 말씀해 주시겠습니까?
Andrei Oniga

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

스냅 샷에서 전체 코드를 게시하고 데이터를 보낼 때까지는 작동하지 않습니다.
Ofir Attia

답변:


437

해당 문자열에서 base64 이미지 데이터를 추출하고 디코딩 한 다음 디스크에 저장할 수 있습니다. 이미 png이므로 GD가 필요하지 않습니다.

$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 = 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

1
@Jon $type은 data : image / jpg 또는 data : image / png 등에 따라 분해에서 값을 할당합니다.
drew010

이 오류가 발생했습니다 : 잘못된 UTF-8 문자가 잘못 인코딩되어 어떻게해야합니까?
aldo

@aldo 아마도 코드와 세부 사항으로 새로운 질문을 게시 할 것입니다. 메시지를 기반으로 코드를 보거나 이미지가 인코딩되는 방식과 스크립트로 전송되는 방법을 알지 못하면 말할 수 없습니다.
drew010

120

이 시도:

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

file_put_contents 문서


4
나는 이것을 시도했지만 data:image/png;base64,파일을 나누는 것을 포함 하고 있습니다.
Michael J. Calkins

2
@MichaelCalkins 나도 그것을 깨뜨린 다. drew010의 답변은 일관되게 작동하는 유일한 솔루션 인 것 같습니다.
David John Welsh

24
data:image/png;base64,다음을 포함하면 전달하는 문자열이 base64_decode유효한 base64가 아닙니다. drew010의 답변이 보여주는 데이터 만 보내면됩니다. 이 답변으로 깨진 것은 없습니다. 이해하지 않고 복사하여 붙여 넣을 수 없으며 "정상 작동"할 것으로 예상합니다.
Cypher

4
base64 콘텐츠가 아닌 질문에 제공된 예제에서는 작동하지 않으며 먼저 조각으로 나눠야합니다 (허용 된 답변 참조).
Benjamin Piette 12

이미지가 성공적으로 저장되었습니다. 그러나 이미지의 URL을 쓰면 빈 이미지가 나타납니다. window.open (dataURL)을 사용하여 테스트했기 때문에 내 dataURL이 올바른지 확신합니다. 왜 빈 이미지입니까?
partho

45

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

희망이 도움이됩니다.


1
당신의 선 $img = str_replace(' ', '+', $img);은 많은 도움이되었습니다. 감사합니다! 왜 전에 공백을 "+"로 변환해야합니까?
Sven

19

논의 된 주제는 RFC 2397- "데이터"URL 체계 ( https://tools.ietf.org/html/rfc2397 )에 설명되어 있습니다.

이 PHP는 이러한 데이터를 처리하는 기본 방법을 가지고 있습니다- "data : stream wrapper"( 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);

2
나는이 답변을 좋아한다. 그러나 성능에 대한 아이디어는 무엇입니까? 예상보다 preg_replace+ 보다 빠릅 file_put_contents니까?
Bonswouar

1
@Bonswouar 감사합니다. 귀하의 질문과 관련하여 : 내 의견으로는 응용 프로그램에 성능 문제가 발생하지 않도록하는 가장 좋은 방법은 환경, 예상 및 허용되는 파일 크기 등을 기준으로 특정 경우에 성능을 측정하는 것입니다. 우리는 여기에서 코드를 사용하여 답변을 시도 할 수 있지만 사실은 정확한 경우 긍정적 인 결과보다 더 많은 해를 입힐 수 있다는 것입니다. 항상 스스로 확인하는 것이 좋습니다 (특히 앱의 성능에 중요한 부분을 말하는 경우).
Vladimir Posvistelik

11

위의 해결책은 jpeg 파일 인 이미지에 달려 있습니다. 내가 사용한 일반적인 솔루션

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

11

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


5

1 선형 솔루션.

$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

drew010 예제를 기반으로 이해하기 쉽도록 실제 예제를 만들었습니다.

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

이 시도...

$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

이 코드는 아래 코드에서 작동합니다.

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

이 기능이 작동합니다. 여기에는 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
        }
    }
}

0

간단 해 :

js 프레임 워크, ajax 요청 또는 모바일 애플리케이션 (클라이언트 측) 내에 파일을 업로드하려고한다고 가정 해 봅시다.

  1. 먼저 base64로 인코딩 된 문자열이 포함 된 데이터 속성을 보냅니다.
  2. 서버 측에서는이를 디코딩하여 로컬 프로젝트 폴더에 저장해야합니다.

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

이미지의 이름을 임의로 바꾸고 데이터베이스의 이미지 경로를 BLOB으로 저장하고 이미지 자체를 폴더에 저장하려는 경우이 솔루션이 도움이됩니다. 웹 사이트 사용자는 원하는만큼 이미지를 저장할 수 있으며 보안을 위해 이미지 이름은 임의로 변경됩니다.

PHP 코드

이미지 이름으로 사용할 임의의 varchar를 생성하십시오.

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

0

PHP는 이미 공정한 대우를 받았습니다. base64-> 파일 변환

나는 이런 식으로 사용하는 데 사용합니다 :

$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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.