Base64 veri dizesinden PNG resmi sunucu tarafında nasıl kaydedilir?


212

Tuval çizimlerini PNG görüntülerine dönüştürmek için Nihilogic'in "Canvas2Image" JavaScript aracını kullanıyorum. Şimdi ihtiyacım olan bu aracın oluşturduğu base64 dizelerini PHP kullanarak sunucudaki gerçek PNG dosyalarına çevirmektir.

Kısacası, şu anda yaptığım şey Canvas2Image kullanarak istemci tarafında bir dosya oluşturmak, daha sonra base64 kodlu verileri almak ve AJAX kullanarak sunucuya göndermek:

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

Bu noktada, "hidden.php" verilere benzeyen bir veri bloğu alır : image / png; base64, iVBORw0KGgoAAAANSUhEUgAABE ...

Bu noktadan sonra, oldukça şaşırdım. Okuduğum kadarıyla, PHP'nin imagecreatefromstring işlevini kullanmam gerektiğine inanıyorum , ancak aslında base64 kodlu dizeden gerçek bir PNG görüntüsü nasıl oluşturulacağından ve sunucumda sakladığından emin değilim. Lütfen yardım edin!


ayrıştırmanız gerekiyor. görüntü türünü oradan ayıklayabilir ve daha sonra base64_decode'u kullanabilir ve bu dizeyi görüntü türünüze göre bir dosyaya kaydedebilirsiniz
Constantin

@Constantine Daha spesifik olabilir misiniz, lütfen?
Andrei Oniga

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

tam kodu, anlık görüntüden gönderebilir ve veri gönderene kadar, benim için çalışmıyor.
Ofir Attia

Yanıtlar:


437

Bu dizeden base64 görüntü verilerini ayıklamanız, kodunu çözmeniz ve daha sonra diske kaydedmeniz gerekir, çünkü zaten bir png olduğundan GD'ye ihtiyacınız yoktur.

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

Ve bir astar olarak:

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

Hataları ayıklamak, kodu çözmek ve kontrol etmek için etkili bir yöntem:

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

Örneğinizde $ türünüz var. Bu değer ne olmalı?
Jon

1
@Jon $type, veriye bağlı olarak patlayandan bir değer alır: görüntü / jpg veya veri: görüntü / png vb.
drew010

Bu hatayı aldım: hatalı biçimlendirilmiş utf-8 karakterleri muhtemelen yanlış kodlanmış ne yapmalıyım?
aldo

@aldo Muhtemelen kod ve ayrıntılarla yeni bir soru gönderin. Sadece bu mesaja dayanarak ve kodunuzu görmeden veya resmin nasıl kodlandığını ve senaryoya nasıl gönderildiğini bilmeden söylemek imkansız.
drew010

120

Bunu dene:

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

file_put_contents dokümanlar


4
Bunu denedim ama data:image/png;base64,hangi dosyayı kırar dahil .
Michael J. Calkins

2
@MichaelCalkins Benim için de kırar. drew010'un yanıtı sürekli çalışan tek çözüm gibi görünüyor.
David John Welsh

24
Eğer dahil ediyorsanız data:image/png;base64,o zaman için geçiyoruz dize base64_decodegeçerli base64 değil. Sadece drew010'un cevabının gösterdiği veriyi göndermeniz gerekir. Bu cevapla kırılmış hiçbir şey yok. Anlamadan kopyalayıp yapıştıramazsınız ve "sadece çalışmasını" bekleyebilirsiniz.
Cypher

4
Temel64 içeriği olmayan ve önce parçalara bölünmesi gereken soruda verilen örnek için çalışmıyor (kabul edilen cevaba bakınız).
Benjamin Piette

resmim başarıyla kaydedildi. ancak resmin URL'sini yazdığımda boş bir resim görüyorum. Window.open (dataURL) kullanarak test ettim, çünkü benim dataURL doğru olduğundan eminim. Neden boş bir resim?
partho

45

str_replace(' ', '+', $img);Bu çalışmayı sağlamak için boşlukları artı sembollerle değiştirmek zorunda kaldım .

İşte tam 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);

Umarım yardımcı olur.


1
Hattın $img = str_replace(' ', '+', $img);bana çok yardımcı oldu, teşekkürler! Neden daha önce alanı "+" ya dönüştürmem gerekiyor?
Sven

19

Tartışılan konunun RFC 2397 - "Veri" URL şemasında belgelendiğini belirtmek gerekir ( https://tools.ietf.org/html/rfc2397 )

Bu PHP nedeniyle bu tür verileri işlemek için yerel bir yol vardır - "veri: akış sarmalayıcı" ( http://php.net/manual/en/wrappers.data.php )

Böylece verilerinizi PHP akışlarıyla kolayca değiştirebilirsiniz:

$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
Bu cevabı beğendim, daha fazla oy olmalı, yerel işlevler kullanıyor, kirli ev yapımı veri manipülasyonu yok! Rağmen, performanslar hakkında herhangi bir fikir? Beklendiği gibi preg_replace+ ' dan daha hızlı file_put_contentsmı?
Eylül

1
@Bonswouar Teşekkürler. Sorunuzla ilgili olarak: bence, uygulamanızın performans sorunlarına sahip olmamasını sağlamanın en iyi yolu, özel durumunuzdaki performansını ölçmek olacaktır (ortama, beklenen ve izin verilen dosya boyutuna vb. Dayalı olarak). Burada kodla oynamayı ve cevapta rakamlar göstermeyi deneyebiliriz, ancak gerçek şu ki, kesin durumunuz için olumlu sonuçtan daha fazla zarar verebilir. Kendi başınıza emin olmak her zaman daha iyidir (özellikle uygulamanın performans açısından kritik kısımlarından bahsediyorsak).
Vladimir Posvistelik

11

Yukarıdaki çözümünüz bir jpeg dosyası olan görüntüye bağlıdır. Genel bir çözüm için kullandım

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

11

@ Dre010 fikrini aldığımda, herhangi bir görüntü türüyle çalışan başka bir işleve genişlettim: PNG, JPG, JPEG veya GIF ve dosya adına benzersiz bir ad veriyor

Ayrı görüntü verisi ve görüntü tipi işlevi

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

Tek doğrusal çözüm.

$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 örneğine dayanarak kolay anlaşılması için çalışan bir örnek yaptım.

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

bunu dene...

$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

Bu kod benim için çalışıyor aşağıdaki kodu kontrol edin:

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

Bu işlev çalışmalıdır. bu, base64 dizesini tutan fotoğraf parametresine ve yenisini kaydederken bağlantısını kaldırmak istediğiniz mevcut bir görüntünüze sahipseniz, mevcut bir görüntü dizinine giden yolu da içerir.

 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

Basit :

Js çerçevesi, ajax isteği veya mobil uygulama (İstemci tarafı) içinde bir dosya yüklemeye çalıştığınızı düşünelim

  1. Öncelikle base64 kodlu bir dize içeren bir veri özniteliği gönderirsiniz.
  2. Sunucu tarafında kodu çözmeniz ve yerel bir proje klasörüne kaydetmeniz gerekir.

PHP kullanarak nasıl yapılır

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

Görüntüleri rastgele yeniden adlandırmak ve hem görüntü yolunu blob olarak hem de görüntünün kendisini klasörlerde depolamak istiyorsanız bu çözüm size yardımcı olacaktır. Web sitesi kullanıcılarınız istedikleri kadar görüntü saklayabilirken, görüntüler güvenlik amacıyla rastgele yeniden adlandırılır.

Php kodu

Resim adı olarak kullanmak için rasgele değişkenler oluşturun.

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

Görüntü veri uzantısını ve base_64 parçasını (verilerden sonraki kısım: image / png; base64,) resimden alın.

$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 zaten adil bir tedavi base64 -> dosya dönüşümü var

Ben bu şekilde kullanarak halletmek için kullanın:

$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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.