2012-07-16 8 views
143

Używam narzędzia JavaScript "Canvas2Image" Nihilogica do konwertowania rysunków na płótnie do obrazów PNG. Potrzebuję teraz przekształcić ciągi base64 generowane przez to narzędzie w rzeczywiste pliki PNG na serwerze, używając PHP.Jak zapisać obraz z serwera PNG po stronie serwera, z łańcucha danych base64

W skrócie, co mam obecnie robi to, aby wygenerować plik po stronie klienta przy użyciu Canvas2Image, a następnie pobrać dane zakodowane base64 i wysłać je do serwera przy użyciu 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 
    } 
}); 

W ten punkt "hidden.php" odbiera blok danych, który wygląda jak dane: image/png; base64, iVBORw0KGgoAAAANSUhEUgAABE ...

Od tego momentu, jestem prawie zakłopotany. Z tego, co przeczytałem, wierzę, że mam użyć funkcji PHP: imagecreatefromstring, ale nie jestem pewien, jak faktycznie utworzyć rzeczywisty obraz PNG z ciągu kodowanego base64 i zapisać go na moim serwerze. Proszę o pomoc!

+0

trzeba go analizować. możesz wyodrębnić typ obrazu stamtąd, a następnie użyć base64_decode i zapisać ten ciąg w pliku według typu obrazu – Constantin

+0

@Constantine Czy możesz bardziej konkretnie, proszę? –

+7

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

Odpowiedz

295

trzeba wyodrębnić dane base64 obrazu z tego łańcucha, dekoduje go, a następnie można zapisać go na dysku, nie trzeba GD od niego już jest 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); 

I jako jedną wkładką:

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

skutecznej metody ekstrakcji, dekodowania i kontroli błędów wynosi:

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

Masz typ $ we własnym przykładzie. Jaka powinna być ta wartość? – Jon

+1

@Jon '$ type' otrzymuje przypisaną wartość od wybuchu, w zależności od tego czy dane: image/jpg lub dane: image/png itp. – drew010

+0

Mam ten błąd: źle sformułowane utf-8 znaków prawdopodobnie niepoprawnie zakodowane co powinienem zrobić? – aldo

97

Spróbuj tego:

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

file_put_contents docs

+3

Próbowałem tego, ale zawiera on 'dane: image/png; base64,', które łamie plik. –

+2

@MichaelCalkins Łamie to również dla mnie. Odpowiedź draw010 wydaje się jedynym rozwiązaniem, które działa konsekwentnie. –

+14

Jeśli uwzględnisz 'dane: image/png; base64,' wtedy łańcuch, który przekazujesz do 'base64_decode' nie jest poprawny base64. Musisz tylko wysłać dane, co ilustruje ilustracja rysunku. Nie ma nic zerwanego z tą odpowiedzią. Nie można kopiować i wklejać bez zrozumienia i oczekiwać, że "po prostu działa". – Cypher

30

miałem zastąpić przestrzenie plus symbol str_replace(' ', '+', $img);, aby to działało.

Oto pełny kod

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

nadzieję, że pomaga.

2

spróbować ...

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

Dobrze rozwiązanie powyżej zależy od obrazu będącego plik jpeg.Dla ogólnego rozwiązania użyłem

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

warto powiedzieć, że omawiany temat jest opisany w dokumencie RFC 2397 - „Dane” schematu URL (https://tools.ietf.org/html/rfc2397)

powodu tej PHP posiada natywny sposób obsłużyć takie dane - "dane: strumień wrapper" (http://php.net/manual/en/wrappers.data.php)

Więc można łatwo manipulować danych z PHP strumieni:

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

podjęciem pomysł @ dre010, mam przedłużony go do innej funkcji, która współpracuje z każdym typem obrazu: PNG, JPG, JPEG lub GIF i daje unikalną nazwę do nazwy pliku

Funkcja danych i obrazu oddzielny obraz typu

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

Rozwiązanie jednoliniowe.

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

Ten kod działa dla mnie sprawdzić poniżej kodu:

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