我在 PHP 上使用扩展 Imagick 将 PDF 文件转换为图像,特定的 PNG 文件。 在转换过程中,整个服务器总是挂起。 我所做的是上传一堆 PDF 文件,循环浏览它及其页面以将其转换为图像。

这是代码。

foreach ($uploaded_file as $key => $value) {
  $upload_file_path = $upload_path.'/'.$value->name;
  $imagick = new Imagick();
  $imagick->setResourceLimit(6, 1);
  $imagick->setResolution(300, 300);
  $imagick->readImage($upload_file_path);
  $pages = $imagick->getNumberImages();

  for ($x=0; $x<$pages; $x++) {
    $imagick->readImage($upload_file_path.'['.$x.']');
    $imagick->setImageFormat('png');
    $imagick->writeImage($image_path.'/page-'.$x.'.png');
  }

  $imagick->clear();
  $imagick->destroy();
}

转换正在进行时,我无法访问服务器上的其他站点,并且转换时间过长。 请帮忙。 谢谢!

#1楼 票数:0

根据 PDF 的内容,转换可能确实非常繁重。 你无能为力。

您已经尝试将线程总数降低到 2,但仍然需要考虑内存、I/O 延迟和 CPU 资源——而且您不知道服务器是否可以使用两个以上的线程。

也许可以做的是尝试和使用降低运行过程中的I / O和CPU优先niceionice如果他们都可用 您需要有一个合适的平台(Linux、BSD 或类似平台),并且可以使用niceionice工具; 并且您需要一个专用的可执行 PHP 进程(那么可能不是 FastCGI)并能够查询其 PID。

在 Linux 系统上,您可能会尝试将转换外包给 ImageMagick 二进制文件,并将其包装在niceionice ,使其变得容易——而且速度很慢。

另一种可能是看是否可以使用ghostscript代替Imagick。

#2楼 票数:0 已采纳

php-vips将 pdf 转换为 png 的速度更快,您可以尝试一下。

我给你做了一个示例程序:

#!/usr/bin/env php
<?php

require __DIR__ . '/vendor/autoload.php';

use Jcupitt\Vips;

for ($i = 1; $i < count($argv); $i++) {
  $image = Vips\Image::newFromFile($argv[$i]);
  $n_pages = $image->get("n-pages");
  echo($argv[$i] . " has " . $n_pages . " pages\n");

  for ($n = 0; $n < $n_pages; $n++) {
    echo("  rendering page " . $n . " ...\n");
    $page = Vips\Image::newFromFile($argv[$i], [
      "dpi" => 300,
      "page" => $n,
      # this enables image streaming
      "access" => "sequential"
    ]);
    $page->writeToFile($argv[$i] . "_page_" . $n . ".png");
  }
}

我可以像这样运行它:

$ /usr/bin/time -f %M:%e ../convert-vips.php nipguide.pdf 
nipguide.pdf has 58 pages
  rendering page 0 ...
...
  rendering page 57 ...
107808:31.72

所以它在 32 秒内制作了 58 个 png,最多需要 110mb 的内存。 它不会创建任何临时文件——110mb 涵盖了所有内容。

png 是一种非常慢的文件格式。 如果保存为 jpg,则所有内容大约需要 6 秒。

我尝试了你的 imagick 代码的一个版本:

#!/usr/bin/env php
<?php

for ($i = 1; $i < count($argv); $i++) {
  $imagick = new Imagick();
  $imagick->setResourceLimit(6, 1);
  $imagick->setResolution(300, 300);
  $imagick->readImage($argv[$i]);
  $pages = $imagick->getNumberImages();
  echo($argv[$i] . " has " . $pages . " pages\n");

  for ($x = 0; $x < $pages; $x++) {
    echo("  rendering page " . $x . " ...\n");
    $imagick->readImage($argv[$i] . "[" . $x . "]");
    $imagick->setImageFormat("png");
    $imagick->writeImage($argv[$i] . "_page_" . $x . ".png");
  }

  $imagick->clear();
  $imagick->destroy();
} 

运行我看到:

$ /usr/bin/time -f %M:%e ../convert-imagick.php nipguide.pdf 
nipguide.pdf has 58 pages
  rendering page 0 ...
...
  rendering page 57 ...
255640:223.26

所以 220 秒(几乎慢了 7 倍)和 260 mb 的内存。 内存使用并不是全部——在 300 DPI 时,imagick 将在 /tmp 中为每个页面创建一个 65mb 的文件,因此它总共需要大约 5GB 的存储空间。

#3楼 票数:0

我想分享我的发现和我认为对我的情况有见地的解决方案。

我注意到每页创建一个新的imagick实例比尝试读取整个文件然后让它 1) 读取页面数量和 2) 让它在所有页面上迭代要快得多。

我只想要 PDF 文件的前 10 页。 当我有一个 50 页的 PDF 文件(大多数只有文本,只有 450KB)时,你阅读这个文件的方式真的很重要。

通过这种方式,它将简单地从第一页开始阅读,并尝试阅读到 10 页。 如果少于 10 个页面,一旦 imagick 抛出错误,它就会意识到它已经到达页面的末尾并停止迭代。

<?php
$reachedLastPage = false;
for ($i = 0; $i <= 10 && empty($reachedLastPage); $i++) {
    $im = new imagick();
    $im->setResolution(300,300);
    try {
        $im->readimage($tempFile.'['.$i.']');
        if ($im->valid()) {
            $im->setImageBackgroundColor('white');
            $im->setImageAlphaChannel(Imagick::VIRTUALPIXELMETHOD_WHITE);
            $im->setImageCompression(imagick::COMPRESSION_JPEG);
            $im->setImageCompressionQuality(60);
            $im->setImageFormat('jpeg');

            $extraFile = microtime(true).'__pdfpage'.".".strtolower('jpg');
            $im->writeImage(rtrim($targetPath) . $extraFile);

            if (is_file(rtrim($targetPath) . $extraFile)) {
                $imageArray[] = $extraFile;
            }
        }
    }
    catch(ImagickException $e) {
        $reachedLastPage = true;
    }
    $im->clear();
    $im->destroy();
}
?>

让我更深入地了解我的其他尝试。

  1. 我首先尝试阅读整个 pdf 文件,然后使用getNumberImages()setIteratorIndex()设置循环并阅读各个页面。 对于 imagick 阅读整个内容将需要很长时间,甚至没有开始处理所有页面。

  2. 也可以使用 imagick 的轻量级实例来查看有多少页,这比让 imagick 尝试读取不存在的页面更简洁:

$im->pingImage($tempFile);
$nrOfPages = $im->getNumberImages();

然而,这在我的测试中已经花费了 10 秒,只是为了阅读页数。 这就是为什么我最终采用了上述方法。

  ask by fsnight translate from so

未解决问题?本站智能推荐:

1回复

无法通过 php 中的 imagick 将 pdf 转换为图像

这是异常跟踪: Postscript 委托失败 `[ghostscript library 8.70] -sstdout=%stderr -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPix
1回复

使用Imagick和PHP将Pdf文件转换为图像

程序可以加载pdf图像,同时使用Imagick将其转换为jpg。但是无法将其转换并加载到Destination目录中。 错误 致命错误:未被捕获的ImagickException:无法打开图像`/opt/ama/mediaFiles/phpe765pr.pdf':/home/j
1回复

使用Imagick和PHP将多页pdf转换为多个JPG图像

我有一个小脚本,可以使用Imagick从上传的多页pdf文件($ uploadfile)创建jpg图片: 这对于1或2页的pdf文档工作正常,但是3页或更多页会出现错误: 错误日志中提到的第152行是: 解决了。 这是一个内存问题。 我将代码更改为: 现
1回复

PHP:Imagick 将多页 pdf 转换为单个图像问题

我正在尝试将多页 pdf 转换为单个图像,其中 pdf 中的所有页面都堆叠在一起。 我正在尝试使用 Imagick() 类。 我发现了类似的问题,但没有一个对这个问题有帮助。 这是我正在使用的代码。 只有 pdf 的最后一页保存在 jpg 文件中,其他页面则没有。 我正在使用 ImageMag
1回复

尝试在Godaddy服务器上使用Imagick创建PDF的jpeg拇指图像时出错

我试图将pdf转换为jpeg缩略图时出现此错误: 在其他任何地方都没有问题,这是在godaddy服务器上PATH是/ sbin:/ usr / sbin:/ bin:/ usr / bin和ghostscript在这里:/ usr / bin / ghostscript 但我不理解
1回复

尝试使用Imagick和PHP保存多个图像时服务器关闭

我已经磕磕绊绊了几天。 我有一个想象对象$img ,它在web服务中读取两页的pdf。 我试图将每个页面保存为jpg图像。 当我删除循环并仅保存一页...一切顺利。 但是通过循环,保存两个页面,它会崩溃,永远不会到达test 7日志语句,并且有时503 server tempora
1回复

如何使用php的imagick将文本转换为图像?

我有一个要转换为图像的文本文件。 我知道如何使用GD执行此操作,但是使用imagick / imagemagick查找合适的功能时遇到问题。
2回复

如何创建质量更好的图像,使用Imagick / PHP将.pdf转换为.jpg?

我目前有一个单页PDF( http://reljac.com/so_1/all.pdf ),这是几个纸质收据的基本扫描。 如果你看PDF,文字清晰易读。 原件是扫描8.5“x 11”纸(无所谓) 我创建了一个非常简单的文件,使用以下代码将PDF转换为.jpg: 当我运行它( h