You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Imagick设JPEG格式仍生成PDF:单页PDF异常问题求助

问题:单页PDF生成PDF文件而非JPG缩略图,多页PDF正常

使用Imagick为自定义管理工具中上传的PDF生成JPG缩略图,已调用setImageFormat('jpeg'),但仅单页PDF会生成PDF文件,多页PDF则可正常生成JPG缩略图。

相关代码

public function generateCopies() {
    if (empty($this->copyPathFormats)) {
        return True;
    }

    if (! is_array($this->copyPathFormats)) {
        throw new \InvalidArgumentException('Asset::copyPathFormat must be an array. '.gettype($this->copyPathFormats).' provided.');
    }

    foreach ($this->copyPathFormats as $key => $copyPathFormat) {
        if ($key === 'finder') {
            continue;
        }

        $path = $this->basePath.$this->pathParamSubstitution($copyPathFormat, $this->pathParam);
        if (! (is_dir($path) || mkdir($path, 0777, True))) {
            throw new \RuntimeException($path.' could not be found or created.');
        }

        $img = new \Imagick($this->path.$this->name);
        $img->setImageCompressionQuality( 89 );
        
        $copyName = $this->name;
        $format = $img->getImageFormat();

        if ($format === 'PDF') {
            $img = new \Imagick();
            $img->setResolution(150,150);
            $img->readImage($this->path.$this->name.'[0]');
            $img->setImageCompressionQuality( 70 );
            $img = $img->flattenImages(); 
            $img->setImageFormat('jpeg');
            $filename  = pathinfo($this->name, PATHINFO_FILENAME);
            $copyName = $filename.'.jpg';
        }

        $geometry = $img->getImageGeometry();
        $width  = $geometry['width'] >= $geometry['height'] ? $this->copySizeConstraints[$key] : 0;
        $height = $geometry['height'] > $geometry['width'] ? $this->copySizeConstraints[$key] : 0;

        if ($img->scaleImage($width,$height,False) !== True) {
            \RuntimeException('Cannot resize the image.');
        }

        if ($img->writeImage($path.$copyName) !== True) {
            throw new \RuntimeException('Cannot write the resized copy to '.$path.$this->name);
        }
        $img->destroy();
    }

    return True;
}

问题原因

核心问题是PDF判断逻辑不可靠:

  • 加载多页PDF时,$img->getImageFormat()返回PDF,进入处理分支,正确生成JPG缩略图。
  • 加载单页PDF时,Imagick会自动将PDF渲染为图像对象,此时$img->getImageFormat()返回渲染后的图像格式(如JPEG),而非PDF,导致跳过PDF处理分支。最终使用原PDF文件名写入,且未设置JPG格式,因此生成的还是PDF文件。

另外代码存在疏漏:\RuntimeException('Cannot resize the image.')仅创建了异常对象,未抛出,无法终止错误流程。

修复方案

1. 改用可靠的PDF识别方式

不要依赖Imagick加载后的格式判断,直接基于原文件属性识别PDF:

方式一:基于文件后缀判断

// 替换原有的$format判断逻辑
$fileExtension = strtolower(pathinfo($this->name, PATHINFO_EXTENSION));
if ($fileExtension === 'pdf') {
    $img->destroy(); // 销毁之前创建的Imagick对象,避免资源泄漏
    $img = new \Imagick();
    $img->setResolution(150,150);
    $img->readImage($this->path.$this->name.'[0]');
    $img->setImageCompressionQuality( 70 );
    $img = $img->flattenImages(); 
    $img->setImageFormat('jpeg');
    $filename  = pathinfo($this->name, PATHINFO_FILENAME);
    $copyName = $filename.'.jpg';
}

方式二:基于MIME类型判断(更准确)

// 替换原有的$format判断逻辑
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($this->path.$this->name);
if ($mimeType === 'application/pdf') {
    $img->destroy(); // 销毁之前创建的Imagick对象,避免资源泄漏
    $img = new \Imagick();
    $img->setResolution(150,150);
    $img->readImage($this->path.$this->name.'[0]');
    $img->setImageCompressionQuality( 70 );
    $img = $img->flattenImages(); 
    $img->setImageFormat('jpeg');
    $filename  = pathinfo($this->name, PATHINFO_FILENAME);
    $copyName = $filename.'.jpg';
}

2. 修复未抛出的异常

将Resize失败的代码修改为:

if ($img->scaleImage($width,$height,False) !== True) {
    throw new \RuntimeException('Cannot resize the image.');
}

内容的提问来源于stack exchange,提问作者awvickers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:33:11