Home > Back-end >  Upload blob with AJAX and move file in the server
Upload blob with AJAX and move file in the server

Time:12-31

I started the project to create a social network with my little programming skills, but I'm stuck: I want to create a posting system like Facebook / Instagram, but the problem is, I want to be able to upload images given by my users to the server directly and not to the database. So I first looked for a way I needed to preview the image, for that I converted the image to Base64 using JS then, I displayed it in my img tag. Then users could submit the form, that's where it gets complicated, because if I understood correctly, you have to convert the image into a Blob to be sent by AJAX so that's what I do in JS except that after it arrived in the PHP file I couldn't find a way to turn it back to Base64 as I realized that PHP doesn't support Blobs or if it does manage it then I was wrong, and I have not found a way to exploit this technology in PHP. So here I am, sending the data is working, no problem, but I still can't upload the images to my server directly, so I tried doing a base64_encode(); but it didn't work, then I tried multiple code from the whole web, but it still didn't work. I saw that on this site there were multiple questions that demand for the same help, but after reading them all well, but in practice it still didn't work, so hopefully I could find some help here and my code after will work. I leave you the code below, and thank you for reading everything. :) Sorry I forgot two things, I wouldn't want to use jQuery in my code, that's why if you give me jQuery I'll try to translate to normal JS, but it's going to be rather difficult so if you don't mind please do not use jQuery. And for the second thing please forgive my English I am a French in high school passionate about code and given that the whole site is in English I did not allow myself to write in French :) My code :

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

And here is the 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  id="<?=$pub['id']?>">
            <div style="height: 52px;">
              <img  height="48px" width="48px" src="IMG/favicon.png" style="float: left; margin-left: 16px">
              <label  style="float: left; margin-left: 8px;margin-top: 12px;font-size: 20px;">Nerzus</label>
              <a  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 >
              <?php if(!empty($pub['img_pub'])){ ?>
                <img src="<?=$pub['img_pub']?>" >
              <?php 
                  }
              ?>
            </div>
            <div>
              <p  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;" >
              <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  style="margin-right: 6px">
                  <div style="height: 30px;width: 30px;"  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  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 >
                  <div style="background-color:white;height: 30px;width: 30px;"  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  id="<?=$pub['id']?>">
            <div style="height: 52px;">
                <img  height="48px" width="48px" src="IMG/favicon.png" style="float: left; margin-left: 16px">
                <label  style="float: left; margin-left: 8px;margin-top: 12px;font-size: 20px;">Nerzus</label>
                <a  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 >
              <?php if(!empty($pub['img_pub'])){ ?>
                <img src="<?=$pub['img_pub']?>" >
              <?php 
                  }
              ?>
            </div>
            <div>
              <p  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;" >
              <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  style="margin-right: 6px">
                  <div style="height: 30px;width: 30px;"  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  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 >
                  <div style="background-color:white;height: 30px;width: 30px;"  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  id="<?=$pub['id']?>">
              <div style="height: 52px;">
                  <img  height="48px" width="48px" src="IMG/favicon.png" style="float: left; margin-left: 16px">
                  <label  style="float: left; margin-left: 8px;margin-top: 12px;font-size: 20px;">Nerzus</label>
                  <a  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 >
                <?php if(!empty($pub['img_pub'])){ ?>
                  <img src="<?=$pub['img_pub']?>" >
                <?php 
                    }
                ?>
              </div>
              <div>
                <p  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;" >
                <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  style="margin-right: 6px">
                    <div style="height: 30px;width: 30px;"  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  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 >
                    <div style="background-color:white;height: 30px;width: 30px;"  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
  }
}
?>

You can see that in my PHP code I put this:

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

It is thanks to this line of code that I believed that I would succeed in converting the blob to Base64 If anyone has the solution to my problem, I thank them in advance. P.S. = I have already tried with Form Data and I have not succeeded I think this is the solution, but I cannot get it to work. Thanks to everyone who read :)

CodePudding user response:

You should not use base64 for file upload. With a large file, your base64 will be extremely large. Although base64 is a relatively efficient way of encoding binary data it will, on average still increase the file size by more than 25%. This increases your bandwidth bill and uploads time. Instead, use the form data to upload the file. Just use base64 to preview the file before upload.

You also don't need to implement an XMLHttpRequest yourself (unless you want your code to work in IE :D) use Fetch API instead.

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

In PHP code, you can get the file from a global variable $_FILES

<?php
// upload.php
var_dump($_FILES['file']);
?>
  • Related