【问题标题】:PHPs base 64_decode is not converting base 64 string to a real workable image filePHP base64_encode 未将 base64 字符串转换为真正可用的图像文件
【发布时间】:2019-07-14 02:32:13
【问题描述】:

大家好,我成功找到了一种方法,该方法声称将文件输入文件转换为 JavaScript 中的 base 64 字符串,因此我成功发送了该 base 64

通过 AJAX 的 JSON 字符串和 base 64 编码字符串看起来像这样在 JSON 方法“photo”中发送:“data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wB etc....”

所以当base 64 字符串到达​​PHP 文件时。 PHP确实很神奇,并成功地将文件存储在我希望文件所在的目标文件夹中,所以当我查看该文件夹时,有一个文件,但是

当我尝试打开照片文件来查看它时,照片查看器应用会显示类似 image.jpg 的内容,看起来我们不支持这种文件格式,而在其他照片查看器应用中它会显示一些内容

类似,所以我做错了什么?

这是我的代码

index.php

<style>

#photo-input{
display: block;
margin-bottom: 50px;
}

</style>

<script>

document.addEventListener('DOMContentLoaded',function(){

document.querySelector('#submit').addEventListener('click',function(){

var photo_input= document.querySelector('#photo-input').files[0];

//Convert #photo-input content into a base 64 string
var reader = new FileReader();
reader.readAsDataURL(photo_input);

reader.onload = function (){
var photo_input_result= reader.result;
sendUploadInfo(photo_input_result);
}
//

});

function sendUploadInfo(photo_input_result){

var photo= photo_input_result;

//<JSON data>

var upload_info = {
    first_name: "John",
    last_name: "Smith",
    photo: photo
};

//</JSON data>

var upload_info_json_object= 'upload_info_json_object='+JSON.stringify(upload_info); 

//<AJAX>
var xhr= new XMLHttpRequest();
xhr.onreadystatechange= function(){

if(xhr.readyState == 4){

document.querySelector('#output').innerHTML= xhr.responseText;

}
}

xhr.open('POST','x');
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(upload_info_json_object);
//</AJAX>
}

});

</script>

<input type='file' id='photo-input'>

<button id='submit'>Send JSON data</button>

<div id='output'></div>

x.php

<?php

$upload_info_json_object = json_decode($_POST['upload_info_json_object']);

$first_name= $upload_info_json_object->first_name;
$last_name= $upload_info_json_object->last_name;


//Photo upload section

$photo= $upload_info_json_object->photo;

base64_decode($photo); 

$path= $_SERVER['DOCUMENT_ROOT'].'/send-json-data-by-ajax/object-based/with-file/2/images/image.jpg';

file_put_contents($path, $photo);

//

?>

<h1><?php echo $first_name.' '.$last_name.' just uploaded a photo.'; ?></h1>

【问题讨论】:

    标签: javascript php base64


    【解决方案1】:

    我认为您应该完全放弃当前的方法并用以下方法替换它:

    <form action="x.php" method="post" enctype="multipart/form-data">
      <input type="hidden" name="first_name" value="John" />
      <input type="hidden" name="last_name" value="Smith" />
      <input type="file" name="photo" accept="image/*" />
      <input type="submit" value="Upload Photo" />
    </form>
    

    然后,在您的服务器端代码上,像这样检查结果:

    <?php
      print_r($_POST); // All of your post fields
      print_r($_FILES); // All of the file uploads
    

    当你知道你想把它放在哪里时,看看move_uploaded_file()

    有很多好处:

    • 真正的二进制文件上传,没有 33% base-64 的浪费和开销,也没有每边的 CPU 来处理它
    • 仅接受图像的图像输入 (accept="image/*")
    • 可以通过屏幕阅读器和其他浏览器控件提交表单,而不仅仅是一些没有上下文的按钮
    • 根本不需要 JavaScript!
    • 标准流式传输上传,以减少服务器上的内存使用量。
    • 无需对可能巨大的 JSON blob 进行编码/解码。

    【讨论】:

    • 不要拿这个私人的,但我不要求其他方法我问我如何才能让这个方法工作,所以我至少可以看到图像我知道所有这些数据传输方法,如 JS FormData()、HTML
      标签等...我知道它们更容易,但出于个人原因,我再次想要这种方法,感谢您尝试帮助 Brad,但这不是我正在寻找的答案,谢谢到目前为止,您的时间。
    【解决方案2】:

    Brad 指出了一种更有效的方法,但是按照您的代码,我看到您保留的字符串不是 base64_decode 的结果。

    改变

    //Photo upload section
    
    $photo=$upload_info_json_object->photo;
    
    base64_decode($photo);
    

    //Photo upload section
    
    $photo=$upload_info_json_object->photo;
    
    $photo=base64_decode($photo);
    

    【讨论】:

      【解决方案3】:

      我发现了几个主要问题:

      1. 在 x.php 的第 13 行,您调用 base64_decode,但不分配结果。如果应该读作$photo = base64_decode($photo);

      2. 用于在浏览器中显示图像的前缀 (data:image/jpeg;base64,) 不应包含在写入的文件中。因此,您的最终解码应该类似于:

      $photo = base64_decode(explode(",",$photo,2)[1]);
      

      explode 在第一个逗号上拆分,返回一个数组,我们只访问包含字符串其余部分的第二个项目,因为我们将它限制为 2 个项目,这意味着如果有一个逗号稍后。 (使用substrstrpos 可能效率更高,所以这也是一个不错的选择)

      如果文件类型并不总是 JPEG,您还需要解析第一部分,以便知道在文件名中使用什么(至少在您关心可移植性的情况下)。


      如果这不能解决您的问题,请逐步开始排除故障:从 JavaScript 中获取值,并在解码之前将其与 PHP 中的值进行比较。他们是一样的吗?通常,您可以根据配置获得一些额外的编码(例如 URL 编码),因此排除这种情况很重要。

      如果字符串看起来相同,我将继续使用base64_decode 函数并将可选的$strict 参数设置为true。如果有任何非 base64 字符,这将导致它返回 false(而不是静默删除它们)。

      您还可以尝试使用已知的小字符串进行测试(绕过编码以确保不是问题),例如 1x1 像素黑色 GIF:

      R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=
      

      您可以直接在 PHP 中进行测试,以消除 JSON 对象的任何编码或解码或其在传输过程中的处理问题。

      【讨论】:

      • 我刚刚发布了一个答案,我更改了您的代码建议并采纳了您的建议,但以不同的方式查看我的答案,让我知道您认为我接下来应该做什么来解决我现在遇到的下一个问题.
      • ThomasWayne,你的内存不足了。 @Brad 的观点是为什么你不应该这样做。通过在接受服务器上设置适当的 CORS 策略已经可以通过 Javascript 表单数据进行跨域上传,并且不涉及字符串的处理。我试图帮助解决最初的问题,以防它可以帮助其他人解决 base64 问题,但我认为你可以为你的用例做很多事情来继续这条道路。
      【解决方案4】:

      嘿,由于某种原因,我发现 JSON 中 base 64 字符串的结构方式似乎在 PHP 端不兼容。我做了一个测试,我将 JSON 对象中的 base 64 编码字符串发送到 PHP 端,并将其与来自

      的同一文件的编码 base 64 字符串进行比较

      https://www.browserling.com/tools/image-to-base64 在 if else 语句中,例如 if 表示它匹配,而 else 表示它不匹配,令我惊讶的是,我发现它给出了我的 else 语句意味着它们与消息不匹配,所以我发现 base 64 字符串的方式是

      在 JavaScript 端编码和结构化在 PHP 端没有被正确读取。 这就是为什么任何照片查看器应用程序都无法读取照片的原因。我假设它在 JSON 编码的 base 64 字符串中的某些字符,但两个比较的字符串都来自我的 if

      else 语句测试看起来完全一样,所以我通过谷歌搜索解决了这个问题 可以在客户端转义特殊字符的方法,我找到了这个方法 调用 encodeURIComponent();它会转义特殊字符,但对于 URL,所以我说我是

      当我在 JSON 对象的编码 base 64 字符串上使用它时,它成功地使 base 64 字符串在 PHP 服务器端可以理解并且我能够毫无问题地查看照片,这让我感到惊讶

      这是我的工作示例

      index.php

      <style>
      
      #photo-input{
      display: block;
      margin-bottom: 50px;
      }
      
      </style>
      
      <script>
      
      document.addEventListener('DOMContentLoaded',function(){
      
      document.querySelector('#submit').addEventListener('click',function(){
      
      var photo_input= document.querySelector('#photo-input').files[0];
      
      //Convert #photo-input content into a base 64 string
      var reader = new FileReader();
      reader.readAsDataURL(photo_input);
      
      reader.onload = function (){
      var photo_input_result= reader.result;
      sendUploadInfo(photo_input_result);
      }
      //
      
      });
      
      function sendUploadInfo(photo_input_result){
      
      //Remove the data:image/file_extension;base64, prefix by not removing this you wont be able to view this as a file in any computing application
      var remove_the_photo_file_reader_prefix= photo_input_result.split(',')[1];
      //
      
      //Escape incompatible characters that won't work properly in JSON and PHP
      var escape_incompatible_characters_from_the_photo= encodeURIComponent(remove_the_photo_file_reader_prefix);
      //
      
      var photo= escape_incompatible_characters_from_the_photo;
      
      //<JSON data>
      
      var upload_info = {
          first_name: "John",
          last_name: "Smith",
          photo: photo
      };
      
      //</JSON data>
      
      var upload_info_json_object= 'upload_info_json_object='+JSON.stringify(upload_info); 
      
      //<AJAX>
      var xhr= new XMLHttpRequest();
      xhr.onreadystatechange= function(){
      
      if(xhr.readyState == 4){
      
      document.querySelector('#output').innerHTML= xhr.responseText;
      
      }
      }
      
      xhr.open('POST','x');
      xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
      xhr.send(upload_info_json_object);
      //</AJAX>
      }
      
      });
      
      </script>
      
      <input type='file' id='photo-input'>
      
      <button id='submit'>Send JSON data</button>
      
      <div id='output'></div>
      

      x.php

      <?php
      
      $upload_info_json_object = json_decode($_POST['upload_info_json_object']);
      
      $first_name= $upload_info_json_object->first_name;
      $last_name= $upload_info_json_object->last_name;
      
      
      //Photo upload section
      $photo= $upload_info_json_object->photo;
      
      //Decode into a file 
      $photo= base64_decode($photo); 
      
      file_put_contents('geeksforgeeks-22.jpg',$photo);
      
      //
      
      ?>
      
      <h1><?php echo $first_name.' '.$last_name.' just uploaded a photo.'; ?></h1>
      

      所以我现在的问题是如果我尝试使用 encodeURIComponent();用 base 64 字符串编码的视频上的方法它给了我这个错误

      未捕获的 RangeError:字符串长度无效

      所以我需要找到另一种方法来转义客户端 JSON 对象中编码的 base 64 字符串中的字符,以使其在 PHP 端可以理解,换句话说,类似于 encodeURIComponent();但不是针对 URL,而是针对客户端上的 base 64 编码字符串,无论客户端上编码的 base 64 字符串有多大。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-03
        • 2014-09-14
        • 1970-01-01
        • 1970-01-01
        • 2013-02-15
        • 2018-09-07
        • 2014-07-21
        相关资源
        最近更新 更多