Ghostscript сжатие PDF-файлов с использованием PHP exe c (Laravel on Docker) - PullRequest
1 голос
/ 02 апреля 2020

Что необходимо сделать:

Пользователь должен иметь возможность загрузить PDF, затем файл загружается в корзину Amazon S3, затем файл должен быть сжат.

Текущий среда:

  • Laravel приложение (смонтировано на Docker) (php:7.4-fpm-alpine3.11, GPL Ghostscript 9.50, Laravel Framework 5.8.37)
  • Корзина Amazon S3 для сохранения документов в
  • Скрипт находится в файле оболочки, который выполняется и добавляется в / usr / local / bin как shrink
  • Оболочка явно не добавляется в контейнер Docker, не так ли?

Текущий поток:

  1. Пользователь загружает файл
  2. Файл загружается в S3
  3. Laravel, затем загружает файл в локальную временную папку
  4. Затем запускается Ghostscript для сжатия указанного файла (этот скрипт )
  5. Сжатый файл загружается обратно на S3

Проблема:

Файл найден и сжимается, но выводится пустой PDF-файл (1 страница, белый).

Dockerfile:

# Add compression shell script to global executables
COPY .docker/config/shrink.sh /usr/local/bin/shrink
RUN chmod u+x /usr/local/bin/shrink
RUN chown nobody.nobody /usr/local/bin/shrink

* 104 4 * это пользователь, PHP работающий на.

PHP функция, которая должна сжимать файл:

public function optimizeFile($file_path)
    {
        // Copy file from default disk to temp disk
        Storage::disk('temp')->put($file_path, Storage::get($file_path));

        $fullTempFilePath = Storage::disk('temp')->path($file_path);

        if (Storage::mimeType($file_path) == 'application/pdf') {
            $output = shell_exec("shrink " . $fullTempFilePath . " " . $fullTempFilePath);
            if ($output != null) {
                Log::error($output);
            }
        } else {
            ImageOptimizer::optimize($fullTempFilePath);
        }

        // Write the compressed file back to default disk
        Storage::put($file_path, Storage::disk('temp')->get($file_path));

        // Delete temp file
        Storage::disk('temp')->delete($file_path);
    }

Если файл не является PDF, ImageOptimizer делает это работа и успешно сжимает образ.

Что я пробовал:

  • (локально) Успешно сжал файл без Docker, используя php artisan serve для запуска Laravel приложения ;
  • (локально) Успешно сжал файл с помощью Docker с использованием docker exec -it <container_id> shrink in.pdf out.pdf;
  • (локально) Успешно сжал файл с помощью Docker в своей оболочке с использованием docker exec -it <container_id> /bin/bash;
  • (Локальный) Мой коллега делал то же самое локально, и ответ также был пустым pdf

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Хорошо, проблема в следующем:

$output = shell_exec("shrink " . $fullTempFilePath . " " . $fullTempFilePath);

Сжатие PDF Ghostscript не работает должным образом, если входные и выходные файлы совпадают. Решение:

$output = shell_exec("shrink " . $fullTempFilePath  . $fullTempFilePath . "-compressed ");
shell_exec("mv " . $fullTempFilePath . "-compressed " . $fullTempFilePath);
0 голосов
/ 02 апреля 2020

ОК, так что первая точка; Ghostscript (точнее, устройство Ghostscript pdfwrite) не сжимает PDF-файлы. Фактический процесс описан в документации в обзоре в VectorDevices.htm. Я рекомендую вам прочитать его.

Во-вторых, вы не можете использовать одно и то же имя для входных и выходных файлов. Ghostscript все еще будет читать из входного файла, в то время как устройство pdfwrite хочет записать в выходной файл.

...