PHP Imagick зависает весь сервер при преобразовании PDF в изображение - PullRequest
0 голосов
/ 19 сентября 2019

Я использую расширение Imagick на PHP для преобразования 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();
}

Я не могу получить доступ к другимсайтов на сервере, пока выполняется преобразование, и преобразование занимает слишком много времени.Пожалуйста помоги.Спасибо!

Ответы [ 2 ]

0 голосов
/ 19 сентября 2019

php-vips быстрее при конвертации pdf в pngs, вы можете попробовать это.

Я сделал вам пример программы:

#!/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], [
    "dpi" => 300,
    # n is number of pages to render, -1 means render all pages in a tall, thin
    # strip 
    "n" => -1,
    # this enables image streaming
    "access" => "sequential"
  ]);

  $page_height = $image->get("page-height");
  $n_pages = $image->get("n-pages");
  echo($argv[$i] . " has " . $n_pages . " pages\n");
  for ($p = 0; $p < $n_pages; $p++) {
    echo("  rendering page " . $p . " ...\n");
    $page = $image->crop(0, $p * $page_height, $image->width, $page_height);
    $page->writeToFile($argv[$i] . "_page_" . $p . ".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

Таким образом, он сделал 58 pngs за 32 секунды и потребовал максимум 110 Мб оперативной памяти.Он не создает никаких временных файлов - эти 110 МБ охватывают все.

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 Мб памяти.Использование памяти - это еще не все - при разрешении 300 DPI imagick создаст 65 МБ файла в / tmp для каждой страницы, поэтому в целом требуется около 5 ГБ памяти.

0 голосов
/ 19 сентября 2019

В зависимости от содержимого PDF, преобразование может быть очень обременительным.Вы мало что можете с этим поделать.

Вы уже пытались снизить общее количество потоков до 2, но все еще есть память, задержка ввода-вывода и ресурсы ЦП, которые необходимо учитывать - и вы неВы не знаете, может ли сервер использовать более двух потоков.

Что вы можете , возможно, сделать, это попытаться понизить приоритет ввода-вывода и ЦП запущенного процесса с помощью nice иionice, если они доступны .У вас должна быть подходящая платформа (Linux, BSD или аналогичная) и доступ к инструментам nice и ionice;и вам нужен выделенный исполняемый процесс PHP (возможно, не FastCGI, а затем), чтобы иметь возможность запрашивать его PID.

В системе Linux вы можете попробовать преобразовать двоичный файл ImageMagick и заключить его в оболочку.в nice и ionice, чтобы сделать его легким - и медленным.

Другая возможность - узнать, можете ли вы использовать ghostscript вместо Imagick.

...