PHP uploaded image broken or half uploaded randomly
Asked Answered
B

1

6

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

Brei answered 21/5, 2021 at 5:54 Comment(3)
Can you turn off the SimpleIamge functionality and try a normal upload with move_uploaded_file without @ do not suppress any errors., once image is uploaded, download that image directly from server and open on your client. Another option to check is get the contents of image and convert it on base64 that is uploaded in tmp dir like base64_encode(file_get_contents($_FILES['loop_logo'])), copy that base 64 string and use in img tag,lastly check your image using readfile() method by adding required headers before reading fileSipper
The first time I kept just move_uploaded_file function only same thing happened and tried without @ also ...I need an alternative option that why I have used that simpleimage function also still the same...will try your base64 method and let you know.Brei
@MohamedAzharuddin try adding mimeType:"multipart/form-data" and remove xhr from $.ajax settings and checkHerbarium
B
4

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.

Brei answered 26/5, 2021 at 6:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.