【问题标题】:PHP uploaded image broken or half uploaded randomlyPHP上传的图片损坏或随机上传一半
【发布时间】:2021-08-10 08:41:40
【问题描述】:

我遇到了一个奇怪的问题。如果我使用 PHP 上传图像并且我上传的图像被破坏或随机上传一半。所以图片在服务器上是这样的:

此外,我只是使用 ajax post 方法,并将 formdata 中的图像发送到 PHP 后端。

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

根据Handle android half uploaded/broken uploaded images to server,我已经验证了上传前和上传后的文件大小。文件大小完全没有变化。

这是我用于文件上传的后端代码。


$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 = '';
}

我已按照此解决方案 Resize image in PHP 之一使用 imagecreatefromjpegimagejpeg 进行文件上传,并尝试正常 @move_uploaded_file 也都有相同的结果。

我的服务器是 Ubuntu 20.04 LTS,我使用的是 PHP v8.0.3 (FPM)、Apache (Apache/2.4.41)。

我也有 cloudflare CDN,我已禁用它并尝试仍然相同。

最后,我检查了 apache 中的错误日志,与任何图像或上传问题完全没有关系。

我的服务器和 tmp 文件夹 (15 GB) 中有足够的空间,并且还有 2.6 GB 的可用内存。

我不知道究竟是什么导致了这个问题。提前致谢

【问题讨论】:

  • 您能否关闭SimpleIamge 功能并尝试使用move_uploaded_file 正常上传而不使用@ 不要抑制任何错误。上传图像后,直接从服务器下载该图像并打开在您的客户端上。检查的另一个选项是获取图像的内容并将其转换为在 tmp 目录中上传的 base64,如base64_encode(file_get_contents($_FILES['loop_logo'])),复制该 base 64 字符串并在img 标签中使用,最后使用readfile() 方法通过添加检查您的图像读取文件前需要的头文件
  • 第一次我只保留 move_uploaded_file 函数只发生了同样的事情,并且没有@也尝试过......我需要一个替代选项,为什么我使用那个 simpleimage 函数也仍然一样......会尝试你的 base64 方法,让你知道。
  • @MohamedAzharuddin 尝试添加mimeType:"multipart/form-data" 并从$.ajax 设置中删除xhr 并检查

标签: php image file-upload brokenimage


【解决方案1】:

我发现了这个错误,我正在结束这个问题。

$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);

我们有一个单独的帖子页面,在那个单独的页面中,我们有一个上面的函数来压缩 meta og:image 的图像。在那个函数中,我们错过了一个逻辑,即创建一个新的压缩版本并单独保存。但是,我们忘记了实现这一点。因此,压缩后,它已经替换了现有文件。由于质量设置为 40,图像被分成了两半。

为什么会随机发生这种情况?

因为,每当有人试图在社交媒体上发布该特定页面时,上述函数 convertImage 就会被触发,而我们手动打开该页面时也会触发同样的情况。

解决方案 我们在这里将质量提高到 100 convertImage($filePath,$new_file_name,100); 并使用新名称 $new_file_name="uploads/".$path_parts['filename']."-min.jpg"; 保存了缩小版本解决了我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2017-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-12
    相关资源
    最近更新 更多