将Base64字符串转换为图像文件?

183
我正在尝试将我的Base64图像字符串转换为图像文件。这是我的Base64字符串:

http://pastebin.com/ENkTrGNG

使用以下代码将其转换为图像文件:
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' );

但是我遇到了一个“无效的图片”错误,这里出了什么问题?

8个回答

316
问题在于编码内容中包含了 data:image/png;base64,,当base64函数对其解码时,这将导致无效的图像数据。在解码字符串之前,在函数中删除该数据,如下所示。
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; 
}

37
我有一个非常聪明的解决方案: $filename_path = md5(time().uniqid()).".jpg"; $decoded=base64_decode($base64_string_img); file_put_contents("uploads/".$filename_path,$decoded); - Rizwan Gill
我只有原始的base64数据,没有任何前缀之类的东西。因此,我不得不将$data [1]更改为$data [0]。 - rcpfuchs
1
@rcpfuchs 如果你只有原始的base64编码,那么为什么需要使用$data?直接按照问题中所写的使用即可。 - Anant
1
老兄,你救了我的命! - Jacky Chong
2
@DanieleTesta,你需要提供一些基准来量化更高效的性能 :) - Austin Brunkhorst
显示剩余9条评论

88

我正在使用的一种简单方法:

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

这个方法非常有效,因为file_get_contents可以读取来自URI的数据,包括data:// URI。


聪明绝顶 - 感谢您的回答。只需记住,实际上您需要在开头加上"data:image/png;base64,",否则file_get_contents()将会失败。 - iateadonut
1
是的,有更好、更简单的解决方案。您可以使用标识符字符串 data:image/png;base64 来创建文件扩展名(如果需要)。 - Fahmi Auliya
1
这里的$output_file是什么? - sd077
在问题的示例中,$output_file是一个输入参数,包含要保存图像的文件名的值。 - Henry Trần
不适用于所有服务器,例如:PHP警告:file_get_contents():由于allow_url_fopen = 0在服务器配置中禁用了data://包装器,因此无法使用... - Ov3rfly
显示剩余4条评论

54
你需要删除图片数据开头的data:image/png;base64,部分,实际的base64数据在此之后。
只需将base64,及其之前的所有内容(在对数据调用base64_decode()之前)剥离掉,就可以了。

1
尝试了不同的解决方案,但这个在任何地方都有效。 - Asfandyar Khan

23

可能就像这样

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

2
这太棒了!非常感谢! 正是我所需要的。只是稍微改动一下以适应我的特定要求,然后就让所有东西都正常工作了。 - Sharpey
1
FYI:$output_file_with_extensionif 语句内部被声明,然后在外部被调用,这将导致某些情况下出现 "Undefined variable $output_file_with_extension ..." 的错误。 - undefined

10

这是一个旧的帖子,但如果您想上传具有相同扩展名的图像-

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

您可以在Laravel的文件系统文件中创建“public_feeds”-

   'public_feeds' => [
        'driver' => 'local',
        'root'   => public_path() . '/uploads/feeds',
    ],

Laravel的filesystem.php和Storage::disk('public_feeds')->put()帮助我解决了问题,使我能够将文件放入我们想要的文件夹中。 - Mohamed Raza

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

5
欢迎来到 Stack Overflow!感谢您提供这段代码片段,它可能会提供一些有限的、即时的帮助。通过展示为什么这是一个好的解决方案,适当的解释将极大地提高其长期价值,并使其对未来有类似问题的读者更有用。请编辑您的答案,添加一些解释,包括您做出的假设。 - Toby Speight
这不是答案,甚至与原问题无关。 - Austin Brunkhorst
@AustinBrunkhorst,这实际上是一个答案,并且与原始问题相关。虽然不是一个好的答案,对OP也没有太多帮助。 - I try so hard but I cry harder

0

这段代码对我有效。

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


-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]";

这对于图像处理已经足够了。特别感谢 Mr. Dev Karan Sharma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接