Convert Base64 string to an image file? [duplicate]
Asked Answered
M

8

186

I am trying to convert my base64 image string to an image file. This is my Base64 string:

http://pastebin.com/ENkTrGNG

Using following code to convert it into an image file:

function base64_to_jpeg( $base64_string, $output_file ) {
    $ifp = fopen( $output_file, "wb" ); 
    fwrite( $ifp, base64_decode( $base64_string) ); 
    fclose( $ifp ); 
    return( $output_file ); 
}

$image = base64_to_jpeg( $my_base64_string, 'tmp.jpg' );

But I am getting an error of invalid image, whats wrong here?

Mailable answered 1/3, 2013 at 8:49 Comment(0)
B
317

The problem is that data:image/png;base64, is included in the encoded contents. This will result in invalid image data when the base64 function decodes it. Remove that data in the function before decoding the string, like so.

function base64_to_jpeg($base64_string, $output_file) {
    // open the output file for writing
    $ifp = fopen( $output_file, 'wb' ); 

    // split the string on commas
    // $data[ 0 ] == "data:image/png;base64"
    // $data[ 1 ] == <actual base64 string>
    $data = explode( ',', $base64_string );

    // we could add validation here with ensuring count( $data ) > 1
    fwrite( $ifp, base64_decode( $data[ 1 ] ) );

    // clean up the file resource
    fclose( $ifp ); 

    return $output_file; 
}
Birdsong answered 1/3, 2013 at 8:58 Comment(13)
i have very smart solution $filename_path = md5(time().uniqid()).".jpg"; $decoded=base64_decode($base64_string_img); file_put_contents("uploads/".$filename_path,$decoded);Grenada
I had just raw base64 data without any prefix or so. therefor I had to change $data[1] to $data[0].Preceptive
@Preceptive if you have just raw base64, then what is the need to use $data,use it direct as written in asked questionDeceit
If you are expecting either, you can use array_pop().Bazar
@Trinh's answer is better for non-raw base64 strings:file_put_contents($output_file, file_get_contents($base64_string));Delaine
You can improve this function with check if $data has really more elements.Gaulish
@JaroslavŠtreit validation is noted in the commentsBirdsong
I don't think this is an efficient way to go about it. Using explode on a large file say 2MB will substantially take a lot of computation time.Matriarchate
@NafiuLawal this is O(n). Feel free to do some benchmarks, but I don't think there's much optimization that can be done without going closer to the metal.Birdsong
@AustinBrunkhorst you are right especially in phpMatriarchate
@AustinBrunkhorst Not much optimisation you can do?? I hope you are joking! Your code goes through the ENTIRE string. Why not do explode(',', $base_string, 1) to stop after finding the comma?? Reading the first 20-ish chars from a string vs (potentially) several MBs? In any case, file_get_contents($base64_string) is waaaay more efficient.Tubman
@DanieleTesta you'll have to provide some benchmarks to quantify waaaay more efficient :)Birdsong
fwrite( $ifp, base64_decode( $data[ 1 ] ) ); this not worked for me. instead of this I used fwrite( $ifp, base64_decode( $base64_string ) );Mahala
P
90

An easy way I'm using:

file_put_contents($output_file, file_get_contents($base64_string));

This works well because file_get_contents can read data from a URI, including a data:// URI.

Pinfold answered 10/4, 2018 at 14:52 Comment(8)
ingenious - thanks for answering. just remember you'll actually NEED data:image/png;base64, at the beginning, or else file_get_contents() will fail.Vespucci
This solution is better than the accepted answer.Lungki
Yes, better & simpler solution. You can make file extension (if needed) using the identifier string data:image/png;base64.Godhead
what is $output_file here?Sondrasone
@Sondrasone In the example in the question, $output_file is an input parameter containing the value of the filename to save the image.Propene
Does not work on all servers, example: PHP Warning: file_get_contents(): data:// wrapper is disabled in the server configuration by allow_url_fopen=0 in ...Primogenitor
@Primogenitor your server config allow_url_fopen is OFF. you can re-enable it in php.ini and try again!Propene
@HenryTrần: Changing server config is not an option here.Primogenitor
B
54

You need to remove the part that says data:image/png;base64, at the beginning of the image data. The actual base64 data comes after that.

Just strip everything up to and including base64, (before calling base64_decode() on the data) and you'll be fine.

Berte answered 1/3, 2013 at 8:53 Comment(1)
Tried different solutions, but this one worked everywhere.Manila
M
23

maybe like this

function save_base64_image($base64_image_string, $output_file_without_extension, $path_with_end_slash="" ) {
    //usage:  if( substr( $img_src, 0, 5 ) === "data:" ) {  $filename=save_base64_image($base64_image_string, $output_file_without_extentnion, getcwd() . "/application/assets/pins/$user_id/"); }      
    //
    //data is like:    data:image/png;base64,asdfasdfasdf
    $splited = explode(',', substr( $base64_image_string , 5 ) , 2);
    $mime=$splited[0];
    $data=$splited[1];

    $mime_split_without_base64=explode(';', $mime,2);
    $mime_split=explode('/', $mime_split_without_base64[0],2);
    if(count($mime_split)==2)
    {
        $extension=$mime_split[1];
        if($extension=='jpeg')$extension='jpg';
        //if($extension=='javascript')$extension='js';
        //if($extension=='text')$extension='txt';
        $output_file_with_extension=$output_file_without_extension.'.'.$extension;
    }
    file_put_contents( $path_with_end_slash . $output_file_with_extension, base64_decode($data) );
    return $output_file_with_extension;
}
Mireillemireles answered 25/5, 2016 at 17:26 Comment(2)
This worked as a charm! Thank you a lot! Exactly what I was looking for. Just changed a little bit to match my specific requirements and got everything to work.Fernferna
FYI : $output_file_with_extension is declared inside the if, then called outside, which will cause an "Undefined variable $output_file_with_extension ..." on some cases.Alga
E
10

That's an old thread, but in case you want to upload the image having same extension-

    $image = $request->image;
    $imageInfo = explode(";base64,", $image);
    $imgExt = str_replace('data:image/', '', $imageInfo[0]);      
    $image = str_replace(' ', '+', $imageInfo[1]);
    $imageName = "post-".time().".".$imgExt;
    Storage::disk('public_feeds')->put($imageName, base64_decode($image));

You can create 'public_feeds' in laravel's filesystem.php-

   'public_feeds' => [
        'driver' => 'local',
        'root'   => public_path() . '/uploads/feeds',
    ],
Escalante answered 31/12, 2018 at 17:39 Comment(1)
laravel's filesystem.php AND Storage::disk('public_feeds')->put() helped me to solve my issue which help me to out files inside the folder we wantDniester
S
0
if($_SERVER['REQUEST_METHOD']=='POST'){
$image_no="5";//or Anything You Need
$image = $_POST['image'];
$path = "uploads/".$image_no.".png";

$status = file_put_contents($path,base64_decode($image));
if($status){
 echo "Successfully Uploaded";
}else{
 echo "Upload failed";
}
}
Stansberry answered 12/10, 2017 at 11:44 Comment(3)
Welcome to Stack Overflow! Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its long-term value by showing why this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you've made.Renettarenew
This is not an answer or even relevant to the original question.Birdsong
@AustinBrunkhorst It actually is an answer and it is relevant to the original question. Although not a good answer or very much helpful to OP.Milli
I
0

This code worked for me.

<?php
$decoded = base64_decode($base64);
$file = 'invoice.pdf';
file_put_contents($file, $decoded);

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}
?>
Illogic answered 21/8, 2019 at 6:41 Comment(0)
I
-5
$datetime = date("Y-m-d h:i:s");
$timestamp = strtotime($datetime);
$image = $_POST['image'];
$imgdata = base64_decode($image);
$f = finfo_open();
$mime_type = finfo_buffer($f, $imgdata, FILEINFO_MIME_TYPE);
$temp=explode('/',$mime_type);
$path = "uploads/$timestamp.$temp[1]";
file_put_contents($path,base64_decode($image));
echo "Successfully Uploaded->>> $timestamp.$temp[1]";

This will be enough for image processing. Special thanks to Mr. Dev Karan Sharma

Iliac answered 10/7, 2018 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.