使用 AJAX 上传 blob 并在服务器中移动文件

Upload blob with AJAX and move file in the server

我用我的一点点编程技巧开始了创建社交网络的项目,但我被卡住了: 我想创建一个像 Facebook / Instagram 这样的发布系统,但问题是,我希望能够将用户提供的图像直接上传到服务器,而不是数据库。所以我首先寻找一种我需要预览图像的方法,为此我使用 JS 将图像转换为 Base64,然后将其显示在我的 img 标签中。然后用户可以提交表单,这就是它变得复杂的地方,因为如果我理解正确,你必须将图像转换为 Blob 以由 AJAX 发送,所以这就是我在 JS 中所做的,除了在它到达之后PHP 文件我找不到将它转回 Base64 的方法,因为我意识到 PHP 不支持 Blob 或者如果它确实管理它那么我错了,我还没有找到在 PHP 中利用此技术的一种方法。所以我在这里,发送数据工作正常,没问题,但我仍然无法将图像直接上传到我的服务器,所以我尝试执行 base64_encode(); 但没有成功,然后我尝试了多个代码来自整个网络,但它仍然没有用。我看到在这个站点上有多个问题需要相同的帮助,但是在阅读完它们之后,但在实践中它仍然没有用,所以希望我能在这里找到一些帮助并且我的代码之后会起作用。我将代码留给您,感谢您阅读所有内容。 :) 对不起,我忘了两件事,我不想在我的代码中使用 jQuery,这就是为什么如果你给我 jQuery 我会尝试翻译成普通的 JS,但这会相当困难因此,如果您不介意,请不要使用 jQuery。第二,请原谅我的英语,我是高中生的法国人,对代码充满热情,鉴于整个网站都是英文的,我不允许自己用法语写作 :) 我的代码:

var getHttpRequest = function () {

     var httpRequest = false;

     if (window.XMLHttpRequest) { //Mozilla,Safari,...

          httpRequest = new XMLHttpRequest();

          if (httpRequest.overrideMimeType) {

               httpRequest.overrideMimeType('text/xml');

          }

     }

     else if (window.ActiveXObject) { //IE

          try {
               httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
          }

          catch (e) {
                         
               try{

                    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
               }

               catch (e) {}
          }
     }
     if (!httpRequest) {
          alert('Abandon :( Impossible de créer une instance XMLHTTP');
          return false;
     }

     return httpRequest;
}
function creapubimg(){
    let httpRequest = getHttpRequest();
    let content = document.getElementById('content_text_area_img').value;
    let imgpub = document.getElementById('chosen-image').src;
    let extention = ['jpeg','png','jpg','gif'];
    let base64ImageContent,contentType,hashtxt;
    var contentTypepost
    let idcountforinclude=0;
    extention.forEach(element => {
        if (imgpub.indexOf(element.value) !== -1){
            base64ImageContent = imgpub.replace('data:image/'+element.value+';base64');
            switch (element.value) {
                case 'jpeg':
                case 'jpg':
                    contentTypepost = 2;
                    contentType = 'image/jpeg'
                    break;
                case 'png':
                    contentTypepost = 3;
                    contentType = 'image/png'
                    break;
                case 'gif':
                    contentTypepost = 1;
                    contentType = 'image/gif'
                    break;
                default:
                    break;
            }
        }
    });
    let base64 = imgpub.replace('data:image/jpeg;base64,', "");
    let blob = b64toBlob(base64,contentType);
    let blobUrl = URL.createObjectURL(blob);
    hashtxt = makeid(24);
    httpRequest.onreadystatechange = function (){
        if(httpRequest.readyState === 1){
          hide_img_panel_reverse();
        }
        if(httpRequest.readyState === 2){
          // faire apparaitre truc de chargment
        }
        if(httpRequest.readyState === 4){
            if(httpRequest.responseText != 'veuiller remplir tout les champs'){
                idcountforinclude += 1;
                let docu = document.getElementById('aff_pub');
                // hide truc de chargment
                let replt = document.createElement('div');
                replt.setAttribute('id', idcountforinclude);
                docu.prepend(replt);
                document.getElementById(idcountforinclude).innerHTML = httpRequest.responseText;
            }
        }
    }
    httpRequest.open('POST','includes/createpubimg.php',true);
    httpRequest.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    httpRequest.send("content_publiction=" + encodeURIComponent(content) + "&img=" + encodeURIComponent(blob) + "&string=" + encodeURIComponent(hashtxt) + "&Content-Type=" + encodeURIComponent(contentTypepost));
}
function b64toBlob(b64Data, contentType='',sliceSize=512){
    let byteCharacters = atob(b64Data);
    let byteArrays = [];
    for(let offset = 0; offset <  byteCharacters.length; offset+=sliceSize){
        
        let slice = byteCharacters.slice(offset,offset + sliceSize);
        let byteNumbers = new Array(slice.length);
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }
        let byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
    }
    let blob = new Blob(byteArrays, {type: contentType});
    return blob;
}

这是 PHP :

<?php
include '../database.php';
        global $db;

if(isset($_POST['img'])){
  if($_POST['Content-Type'] == 1) {
    $hashchemin = crypt($_POST['string'], 'piafou');
    $hashchemin = rtrim($hashchemin, '/\');
    $chemin = 'img_pub/'.$hashchemin.'.gif';  
    if(isset($_POST['content_publication'])){
      if(!empty($_POST['content_publication'])){
        $content = $_POST['content_publication'];
        $Blobimg = $_POST['file'];
        $Base64img = "data:image/png;base64," . base64_encode($Blobimg) . "";
        move_uploaded_file(base64_decode($Base64img), $chemin);
        $ins = $db->prepare('INSERT INTO publications (content, img_pub) VALUES (:content, :img_pub)');
        $ins->execute([
          'content' => $content,
          'img_pub' => $chemin
        ]);
        $publications =$db->query('SELECT * FROM publications ORDER BY id DESC LIMIT 60');
        $pub = $publications->fetch();
        ?>
          <div class="aff_pub_div_content" id="<?=$pub['id']?>">
            <div style="height: 52px;">
              <img class="nonSelectionnable" height="48px" width="48px" src="IMG/favicon.png" style="float: left; margin-left: 16px">
              <label class="nonSelectionnable" style="float: left; margin-left: 8px;margin-top: 12px;font-size: 20px;">Nerzus</label>
              <a class="button-edit nonSelectionnable" onclick="hide_edit_panel(<?= $pub['id'] ?>)" style="text-decoration: none; color: #807c7cc4; margin-right: 20px; font-size: 12.6px; float: right; cursor: pointer;">●●●</a>
            </div>
            <div class="nonSelectionnable">
              <?php if(!empty($pub['img_pub'])){ ?>
                <img src="<?=$pub['img_pub']?>" class="img_pub_aff">
              <?php 
                  }
              ?>
            </div>
            <div>
              <p class="text_pub_aff" id="<?="content_".$pub['id']?>">
                <?php 
                  $pub_content = $_POST['content_publication'];
                  $pub_content = htmlspecialchars($pub_content, ENT_HTML5);
                  $pub_content = nl2br($pub_content);
                  echo($pub_content);
                ?>  
              </p>
            </div>
            <div style="background-color:#d6d6dd;height:1px;width:96%;margin-top:10px; margin-right:auto;margin-left:auto;"></div>
            <div style="text-align: left;" class="nonSelectionnable">
              <ul style="margin-top: 6px; margin-left: 20px">
                <?php 
                  $likepub = $db->prepare('SELECT * FROM like_pub WHERE pub = :pub AND user = :user');
                  $likepub->execute([
                    'user' => 16,
                    'pub' => $pub['id']
                  ]);
                  if($likepub->rowCount() ==1) {
                ?> 
                <style type="text/css">
                  .phpdecidelikecolordiv-<?=$pub['id']?>{
                    background-color: red;
                  }
                </style>
                <?php
                  }
                  else{
                ?>
                <style type="text/css">
                  .phpdecidelikecolordiv-<?=$pub['id']?>{
                    background-color: white;
                  }
                </style>
                <?php
                  }
                ?>
                <li class="exp_article" style="margin-right: 6px">
                  <div style="height: 30px;width: 30px;" class="like_article phpdecidelikecolordiv-<?=$pub['id']?>" id="like-div-<?=$pub['id']?>">
                    <a style="cursor: pointer;" onclick="like_db(16,<?=$pub['id']?>,<?=$pub['id']?>);">
                      <img src="IMG/love.png" height="30px" width="30px" id="like">
                    </a>
                  </div>
                </li>
                <li class="exp_article" style="color: black;font-size: 24px;font-family: 'Oswald', sans-serif;;vertical-align: top;margin-top: -3px; margin-right: 16px;" id="likepart-<?=$pub['id']?>"><?php $idpublike = $pub['id'];$likerecup = $db->prepare('SELECT * FROM like_pub WHERE pub = :id');$likerecup->execute(['id' => $idpublike]);$likecount = $likerecup->rowCount();echo $likecount;?></li>
                <li class="exp_article">
                  <div style="background-color:white;height: 30px;width: 30px;" class="comment_article" id="comment-div-<?=$pub['id']?>"><a style="cursor: pointer;" onclick="comment_aff(<?=$pub['id']?>);"><img src="IMG/chat-bubble.png" height="30px" width="30px" id="comment"></a></div>
                </li>
              </ul>
            </div>
          </div>
        <?php
      }
      else{
        echo('Veuiller remplir tout les champs');
      } 
    }
  }
  elseif($_POST['Content-Type'] == 2){
    $hashchemin = crypt($_POST['string'], 'piafou');
    $hashchemin = rtrim($hashchemin, '/\');
    $chemin = 'img_pub/'.$hashchemin.'.jpeg';
    if(isset($_POST['content_publication'])){
      if(!empty($_POST['content_publication'])){
        $content = $_POST['content_publication']; 
        $Blobimg = $_POST['file'];
        $Base64img = "data:image/png;base64," . base64_encode($Blobimg) . "";
        move_uploaded_file(base64_decode($Base64img), $chemin);
        $ins = $db->prepare('INSERT INTO publications (content, img_pub) VALUES (:content, :img_pub)');
        $ins->execute([
          'content' => $content,
          'img_pub' => $chemin
        ]);
        $publications =$db->query('SELECT * FROM publications ORDER BY id DESC LIMIT 60');
        $pub = $publications->fetch();
        ?>
          <div class="aff_pub_div_content" id="<?=$pub['id']?>">
            <div style="height: 52px;">
                <img class="nonSelectionnable" height="48px" width="48px" src="IMG/favicon.png" style="float: left; margin-left: 16px">
                <label class="nonSelectionnable" style="float: left; margin-left: 8px;margin-top: 12px;font-size: 20px;">Nerzus</label>
                <a class="button-edit nonSelectionnable" onclick="hide_edit_panel(<?= $pub['id'] ?>)" style="text-decoration: none; color: #807c7cc4; margin-right: 20px; font-size: 12.6px; float: right; cursor: pointer;">●●●</a>
            </div>
            <div class="nonSelectionnable">
              <?php if(!empty($pub['img_pub'])){ ?>
                <img src="<?=$pub['img_pub']?>" class="img_pub_aff">
              <?php 
                  }
              ?>
            </div>
            <div>
              <p class="text_pub_aff" id="<?="content_".$pub['id']?>">
                <?php 
                  $pub_content = $_POST['content_publication'];
                  $pub_content = htmlspecialchars($pub_content, ENT_HTML5);
                  $pub_content = nl2br($pub_content);
                  echo($pub_content);
                ?>  
              </p>
            </div>
            <div style="background-color:#d6d6dd;height:1px;width:96%;margin-top:10px; margin-right:auto;margin-left:auto;"></div>
            <div style="text-align: left;" class="nonSelectionnable">
              <ul style="margin-top: 6px; margin-left: 20px">
                <?php 
                  $likepub = $db->prepare('SELECT * FROM like_pub WHERE pub = :pub AND user = :user');
                  $likepub->execute([
                    'user' => 16,
                    'pub' => $pub['id']
                  ]);
                  if($likepub->rowCount() ==1) {
                ?> 
                <style type="text/css">
                  .phpdecidelikecolordiv-<?=$pub['id']?>{
                    background-color: red;
                  }
                </style>
                <?php
                  }
                  else{
                ?>
                <style type="text/css">
                  .phpdecidelikecolordiv-<?=$pub['id']?>{
                    background-color: white;
                  }
                </style>
                <?php
                  }
                ?>
                <li class="exp_article" style="margin-right: 6px">
                  <div style="height: 30px;width: 30px;" class="like_article phpdecidelikecolordiv-<?=$pub['id']?>" id="like-div-<?=$pub['id']?>">
                    <a style="cursor: pointer;" onclick="like_db(16,<?=$pub['id']?>,<?=$pub['id']?>);">
                      <img src="IMG/love.png" height="30px" width="30px" id="like">
                    </a>
                  </div>
                </li>
                <li class="exp_article" style="color: black;font-size: 24px;font-family: 'Oswald', sans-serif;;vertical-align: top;margin-top: -3px; margin-right: 16px;" id="likepart-<?=$pub['id']?>"><?php $idpublike = $pub['id'];$likerecup = $db->prepare('SELECT * FROM like_pub WHERE pub = :id');$likerecup->execute(['id' => $idpublike]);$likecount = $likerecup->rowCount();echo $likecount;?></li>
                <li class="exp_article">
                  <div style="background-color:white;height: 30px;width: 30px;" class="comment_article" id="comment-div-<?=$pub['id']?>"><a style="cursor: pointer;" onclick="comment_aff(<?=$pub['id']?>);"><img src="IMG/chat-bubble.png" height="30px" width="30px" id="comment"></a></div>
                </li>
              </ul>
            </div>
          </div>
        <?php
      }
      else{
        echo('Veuiller remplir tout les champs');
      } 
    } 
  }
  elseif($_POST['Content-Type'] == 3){
    $hashchemin = crypt($_POST['string'], 'piafou');
    $hashchemin = rtrim($hashchemin, '/\');
    $chemin = 'img_pub/'.$hashchemin.'.png';
    if(isset($_POST['content_publication'])){
      if(!empty($_POST['content_publication'])){
        $content = $_POST['content_publication'];
        $Blobimg = $_POST['file'];
        $Base64img = "data:image/png;base64," . base64_encode($Blobimg) . "";
        move_uploaded_file(base64_decode($Base64img), $chemin);
        $ins = $db->prepare('INSERT INTO publications (content, img_pub) VALUES (:content, :img_pub)');
        $ins->execute([
          'content' => $content,
          'img_pub' => $chemin
        ]);
        $publications =$db->query('SELECT * FROM publications ORDER BY id DESC LIMIT 60');
        $pub = $publications->fetch();
        ?>
          <div class="aff_pub_div_content" id="<?=$pub['id']?>">
              <div style="height: 52px;">
                  <img class="nonSelectionnable" height="48px" width="48px" src="IMG/favicon.png" style="float: left; margin-left: 16px">
                  <label class="nonSelectionnable" style="float: left; margin-left: 8px;margin-top: 12px;font-size: 20px;">Nerzus</label>
                  <a class="button-edit nonSelectionnable" onclick="hide_edit_panel(<?= $pub['id'] ?>)" style="text-decoration: none; color: #807c7cc4; margin-right: 20px; font-size: 12.6px; float: right; cursor: pointer;">●●●</a>
              </div>
              <div class="nonSelectionnable">
                <?php if(!empty($pub['img_pub'])){ ?>
                  <img src="<?=$pub['img_pub']?>" class="img_pub_aff">
                <?php 
                    }
                ?>
              </div>
              <div>
                <p class="text_pub_aff" id="<?="content_".$pub['id']?>">
                  <?php 
                    $pub_content = $_POST['content_publication'];
                    $pub_content = htmlspecialchars($pub_content, ENT_HTML5);
                    $pub_content = nl2br($pub_content);
                    echo($pub_content);
                  ?>  
                </p>
              </div>
              <div style="background-color:#d6d6dd;height:1px;width:96%;margin-top:10px; margin-right:auto;margin-left:auto;"></div>
              <div style="text-align: left;" class="nonSelectionnable">
                <ul style="margin-top: 6px; margin-left: 20px">
                  <?php 
                    $likepub = $db->prepare('SELECT * FROM like_pub WHERE pub = :pub AND user = :user');
                    $likepub->execute([
                      'user' => 16,
                      'pub' => $pub['id']
                    ]);
                    if($likepub->rowCount() ==1) {
                  ?> 
                  <style type="text/css">
                    .phpdecidelikecolordiv-<?=$pub['id']?>{
                      background-color: red;
                    }
                  </style>
                  <?php
                    }
                    else{
                  ?>
                  <style type="text/css">
                    .phpdecidelikecolordiv-<?=$pub['id']?>{
                      background-color: white;
                    }
                  </style>
                  <?php
                    }
                  ?>
                  <li class="exp_article" style="margin-right: 6px">
                    <div style="height: 30px;width: 30px;" class="like_article phpdecidelikecolordiv-<?=$pub['id']?>" id="like-div-<?=$pub['id']?>">
                      <a style="cursor: pointer;" onclick="like_db(16,<?=$pub['id']?>,<?=$pub['id']?>);">
                        <img src="IMG/love.png" height="30px" width="30px" id="like">
                      </a>
                    </div>
                  </li>
                  <li class="exp_article" style="color: black;font-size: 24px;font-family: 'Oswald', sans-serif;;vertical-align: top;margin-top: -3px; margin-right: 16px;" id="likepart-<?=$pub['id']?>"><?php $idpublike = $pub['id'];$likerecup = $db->prepare('SELECT * FROM like_pub WHERE pub = :id');$likerecup->execute(['id' => $idpublike]);$likecount = $likerecup->rowCount();echo $likecount;?></li>
                  <li class="exp_article">
                    <div style="background-color:white;height: 30px;width: 30px;" class="comment_article" id="comment-div-<?=$pub['id']?>"><a style="cursor: pointer;" onclick="comment_aff(<?=$pub['id']?>);"><img src="IMG/chat-bubble.png" height="30px" width="30px" id="comment"></a></div>
                  </li>
                </ul>
              </div>
          </div>
        <?php
      }
      else{
        echo('Veuiller remplir tout les champs');
      } 
    }
  }
  else{
    // message d'erreur
  }
}
?>

你可以在我的 PHP 代码中看到我把这个:

$Base64img = "data:image/png;base64," . base64_encode($Blobimg) . "";

多亏了这行代码,我相信我能成功将blob转换为Base64 如果有人能解决我的问题,我提前感谢他们。 P.S。 = 我已经尝试使用 Form Data 但没有成功 我认为这是解决方案,但我无法让它工作。 感谢所有阅读的人:)

您不应使用 base64 进行文件上传。对于大文件,您的 base64 将非常大。尽管 base64 是一种相对有效的二进制数据编码方式,但它平均仍会将文件大小增加 25% 以上。这会增加您的带宽费用和上传时间。相反,使用表单数据上传文件。只需在上传前使用 base64 预览文件即可。

您也不需要自己实现 XMLHttpRequest(除非您希望您的代码在 IE 中工作 :D)请改用 Fetch API

  <input id="file-upload" type="file" name="file" onchange="readFile()" /> 
  <button id="upload-button" onclick="uploadFile()"> Upload </button>
  <script>

   function readFile() {
  
     if(this.files && this.files[0]) {
    
       const fileReader = new FileReader();
    
       fileReader.addEventListener("load", function(e) {
        //you can use base64 to preview file
        console.log('Base64:', e.target.result);
       }); 
    
       fileReader.readAsDataURL( this.files[0] );
     }
  
   }


   function uploadFile() {
      const formData = new FormData(); 
      const fileUploadInput = document.getElementById('file-upload');
      formData.append("file", fileUploadInput.files[0]);
      
      fetch('/upload.php', {
        method: "POST", 
        body: formData
      })
      .then(() => {
       console.log('Success');
      })
     .catch(error => {
       console.error('Error:', error);
      });
  }
  </script>

在PHP代码中,您可以从全局变量$_FILES

中获取文件
<?php
// upload.php
var_dump($_FILES['file']);
?>