Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP uploaded image broken or half uploaded randomly

I am facing a weird problem. If I upload an image using PHP and my uploaded image got broken or half uploaded randomly. So the image appears like this on the server:

greyed out half-broken image

Moreover, I am just using the ajax post method and send an image within the formdata to the PHP backend.

var formData = new FormData();
formData.append('loop_logo', $('.loop_logo_public')[0].files[0]);
var image = $('.loop_logo_public')[0].files[0];
var fsize = image.size;
formData.append('file_size',fsize);

$.ajax({

    xhr: function() {
        var xhr = new window.XMLHttpRequest();
        return xhr;
    },
    method: 'post',
    url: mainurl + 'api.php?type=create_post',
    contentType: false,
    processData: false,
    data: formData
}).done(function(data) {

    //other actions
});

as per this Handle android half uploaded/broken uploaded images to server I have validated the filesize from before upload and after upload also. There is no change in file size at all.

here is my backend code for file upload.


$mainurl="https://example.com/";

class SimpleImage {
   var $image;
   var $image_type;
   function load($filename) {
      $image_info = getimagesize($filename);
      $this->image_type = $image_info[2];
      if( $this->image_type == IMAGETYPE_JPEG ) {
         $this->image = imagecreatefromjpeg($filename);
      } elseif( $this->image_type == IMAGETYPE_GIF ) {
         $this->image = imagecreatefromgif($filename);
      } elseif( $this->image_type == IMAGETYPE_PNG ) {
         $this->image = imagecreatefrompng($filename);
      }
   }
   function save($filename, $image_type=IMAGETYPE_JPEG, $compression=100, $permissions=null) {
      if( $image_type == IMAGETYPE_JPEG ) {
         imagejpeg($this->image,$filename,$compression);     
      } elseif( $image_type == IMAGETYPE_GIF ) {
         imagegif($this->image,$filename);
      } elseif( $image_type == IMAGETYPE_PNG ) {
         imagepng($this->image,$filename);
      }
      if( $permissions != null) {
         chmod($filename,$permissions);
      }
      return true;  
   }
}

function uploadFile($file, $name)
{
 $target = basename($file["name"]);
  $imageFileType = strtolower(pathinfo($target,PATHINFO_EXTENSION));
  $dest = $mainurl."uploads/".$name.".".$imageFileType;
  $dest2 = "uploads/".$name.".".$imageFileType;
 
if($imageFileType == "jpg" || $imageFileType == "png" || $imageFileType == "jpeg" || $imageFileType == "gif")
{
    $image = new SimpleImage();
    $image->load($file["tmp_name"]);
    $image_info = getimagesize($file["tmp_name"]);
    $image_type = $image_info[2];
    if($image->save($dest2,$image_type,100))
    {
    return "uploads/".$name.".".$imageFileType;
    }
    else{
    if(@move_uploaded_file($file["tmp_name"], $dest)){
      return "uploads/".$name.".".$imageFileType;
    }else{
      return '';
    }
    }
}

    
  }else{
    return '';
  }
}


if (isset($_FILES['loop_logo'])) {
    $backsize = $_FILES['loop_logo']['size'];
    $rsize = $_POST['file_size'];
    if ($rsize == $backsize) {
        $loop_logo = uploadFile($_FILES['loop_logo'], rand(9999, 9999999).time(), $mainurl);
    }
} else {
    $loop_logo = '';
}

I have followed one of this solution Resize image in PHP for file upload with imagecreatefromjpeg and imagejpeg and tried normal @move_uploaded_file also both are having the same results.

My server is Ubuntu 20.04 LTS and I am using PHP v8.0.3 (FPM), Apache (Apache/2.4.41).

I am having cloudflare CDN also, I have disabled that and tried still the same.

Finally, I have checked the error log in apache nothing is related to any image or upload problem at all.

I am having plenty of space in my server and tmp folder (15 GB) and having 2.6 GB free Ram also.

I don't know what exactly causing the issue. Thanks in advance

like image 458
Mohamed Azharuddin Avatar asked May 21 '21 05:05

Mohamed Azharuddin


1 Answers

I have found the bug and I am closing this question.

$filePath=$post['post_image'];


function convertImage($originalImage, $outputImage, $quality)
{
    // jpg, png, gif or bmp?
    $exploded = explode('.',$originalImage);
    $ext = $exploded[count($exploded) - 1];

    if (preg_match('/jpg|jpeg/i',$ext))
        $imageTmp=imagecreatefromjpeg($originalImage);
    else if (preg_match('/png/i',$ext))
        $imageTmp=imagecreatefrompng($originalImage);
    else if (preg_match('/gif/i',$ext))
        $imageTmp=imagecreatefromgif($originalImage);
    else if (preg_match('/bmp/i',$ext))
        $imageTmp=imagecreatefrombmp($originalImage);
    else
        return 0;

    // quality is a value from 0 (worst) to 100 (best)
    imagejpeg($imageTmp, $outputImage, $quality);
    imagedestroy($imageTmp);


    return 1;
}

$path_parts = pathinfo($filePath);

$new_file_name="uploads/".$path_parts['filename'].".jpg";
convertImage($filePath,$new_file_name,40);

We have a separate post page and in that individual page, we are having an above function to compress the image for meta og:image. In that function, we missed one logic that is to create a new compressed version and save it separately. However, we forget to implement that. Therefore, after the compress, it has replaced the existing file. Due to the quality was set to 40 image was broken in half.

Why this has happened randomly?

Because, whenever someone trying to post that particular page in social media, the above function convertImage got triggered as well as we have opened that page manually also triggered the same.

Solution We have increased the quality to 100 here convertImage($filePath,$new_file_name,100); and saved the minified version with new name $new_file_name="uploads/".$path_parts['filename']."-min.jpg"; solved my problem.

like image 199
Mohamed Azharuddin Avatar answered Oct 17 '22 17:10

Mohamed Azharuddin