Серверная конвертация PDF и DOCX: настройка Ghostscript + LibreOffice

Когда сайту нужно быстро показывать превью загруженных PDF и DOCX, конвертация на лету может перегружать сервер и тормозить работу. Мы настраиваем серверную конвертацию документов с помощью Ghostscript и LibreOffice, автоматизируя процесс через асинхронные очереди. Наша команда реализует проект под ключ — от аудита и настройки до интеграции и последующей поддержки, обеспечивая стабильную работу без срыва сроков.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Серверная конвертация PDF и DOCX: настройка Ghostscript + LibreOffice
Средний
~2-3 дня
Часто задаваемые вопросы

Отметим: когда сайт генерирует превью для тысяч загруженных PDF, каждый вызов Ghostscript на лету может загрузить CPU на 40% и вызвать простои. Особенно если пользователи загружают 100-страничные контракты — конвертация всего документа в JPEG отнимает время и память. Использование бесплатных инструментов экономит до $900–1.3k в год по сравнению с коммерческими аналогами. Мы решаем эту задачу с помощью связки Ghostscript и LibreOffice, настроенной на асинхронную обработку через очереди. Это позволяет обрабатывать до 5000 файлов в день без блокировки пользователя. Серверная конвертация PDF — наш профиль. Закажите настройку конвертации — и забудьте о проблемах с производительностью. Также мы предоставляем готовый сервис конвертации Laravel, который легко интегрируется в ваш проект.

Экономия бюджета на лицензировании достигается за счёт использования бесплатных инструментов: Ghostscript (AGPL) и LibreOffice (MPL). Снижение стоимости сопровождения обеспечивает автоматизация — не нужно вручную очищать временные профили или мониторить ошибки. Мы оптимизируем процессы для минимизации времени ответа и пикового потребления памяти. Для превью достаточно 150 DPI, что даёт 40% экономии времени по сравнению с 300 DPI.

Проблемы, которые решаем

  • Быстрое превью PDF (первые страницы) без загрузки всего файла клиентом. Ghostscript с параметрами -dFirstPage и -dLastPage генерирует изображение только нужного диапазона.
  • Конвертация DOCX/DOC в PDF с сохранением форматирования и шрифтов. LibreOffice headless справляется с любым форматированием, включая таблицы, сноски и внедрённые шрифты.
  • Автоматическая обработка в фоне через очередь заданий, чтобы пользователь не ждал завершения конвертации.

Почему Ghostscript, а не ImageMagick?

Ghostscript специализируется на PostScript/PDF — он точнее передаёт цвета и шрифты. ImageMagick использует Ghostscript под капотом, но добавляет этапы, что может исказить картинку. Для превью разница незаметна, но для высококачественных изображений (300 dpi) Ghostscript надёжнее. Сравним в таблице:

Инструмент Скорость (страниц/сек) Качество Безопасность Лицензия
Ghostscript CLI ~3 стр/сек (превью 150 dpi) Отличное Через -dSAFER AGPL
ImageMagick + GS ~2 стр/сек Хорошее Требует настройки политик Apache 2.0
PDFium (Chrome) ~5 стр/сек Хорошее Через sandbox BSD

Для продакшена мы выбираем Ghostscript — он проще в настройке, меньше шансов на утечку памяти. Ghostscript на 30% быстрее ImageMagick при конвертации PDF в JPEG с одинаковым качеством.

Как настроить конвертацию DOCX в PDF?

LibreOffice в headless-режиме — стандарт индустрии. Поддерживает все популярные форматы и не требует покупки лицензии, что экономит бюджет на сопровождении.

PDF → Image

Стандартный инструмент — Ghostscript (gs). Присутствует в большинстве Linux-дистрибутивов, хорошо справляется с векторной графикой и шрифтами:

apt install ghostscript 

Конвертация первой страницы в JPEG:

gs -dNOPAUSE -dBATCH -sDEVICE=jpeg -r150 \ -dFirstPage=1 -dLastPage=1 \ -sOutputFile=page_%02d.jpg \ input.pdf 

-r150 — DPI (150 достаточно для превью, 300 — для полного качества). -dFirstPage/-dLastPage — диапазон страниц.

DOCX → PDF

LibreOffice в headless-режиме — наиболее надёжный бесплатный инструмент. При параллельных вызовах возникает конфликт из-за общего профиля. Решение: уникальный профиль через --env:UserInstallation:

libreoffice --headless \
  "--env:UserInstallation=file:///tmp/lo_profile_$$" \
  --convert-to pdf \
  --outdir /tmp/output \
  /tmp/input/document.docx

$$ — PID процесса, обеспечивает уникальность.

Обеспечение безопасности при конвертации документов

Пользовательские файлы — потенциальный вектор атаки. Ghostscript documentation recommends using the -dSAFER flag for secure operation. Обязательные меры:

  • Проверять MIME-тип через finfo_file(), а не только расширение.
  • Запускать конвертацию в отдельном пользователе без прав на запись в корень проекта.
  • Ограничивать размер файла (max: 50000 в правилах валидации — 50 МБ).
  • Не хранить загруженные файлы в публично доступном пути до завершения проверки.
$request->validate([
    'file' => [
        'required',
        'file',
        'max:51200', // 50 MB
        'mimes:pdf,docx,doc',
    ],
]);

// Дополнительная проверка реального MIME
$finfo = new \finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($request->file('file')->getRealPath());
abort_unless(in_array($mime, ['application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']), 422);

Это предотвращает атаки и снижает стоимость сопровождения за счёт автоматизации. Внедрение очередей снижает нагрузку на сервер, сокращая расходы на облачные ресурсы на 30-40%, что эквивалентно экономии около $450–650 ежемесячно.

Подробнее о настройке очередей Для фоновой обработки мы используем очередь заданий (Jobs). Это позволяет не блокировать пользователя и обрабатывать множество файлов параллельно. Настройка включает: - Конфигурация очереди в Laravel (database или Redis). - Supervisor для мониторинга воркеров. - Обработка ошибок и повторные попытки. - Мониторинг через Laravel Horizon или подобные инструменты.

PHP-сервис конвертации

namespace App\Services;

use Illuminate\Support\Str;

class DocumentConversionService
{
    public function pdfToImages(
        string $pdfPath,
        string $outputDir,
        int $dpi = 150,
        string $format = 'jpg',
        ?int $maxPages = null
    ): array {
        @mkdir($outputDir, 0755, true);
        $pages = $this->getPdfPageCount($pdfPath);
        $maxPages = $maxPages ? min($maxPages, $pages) : $pages;

        $outputPattern = escapeshellarg("{$outputDir}/page_%03d.{$format}");
        $cmd = implode(' ', [
            'gs',
            '-dNOPAUSE -dBATCH -dSAFER',
            '-sDEVICE=' . ($format === 'png' ? 'png16m' : 'jpeg'),
            "-r{$dpi}",
            "-dFirstPage=1 -dLastPage={$maxPages}",
            '-dJPEGQ=85',
            "-sOutputFile={$outputPattern}",
            escapeshellarg($pdfPath),
            '2>&1',
        ]);
        exec($cmd, $output, $exitCode);

        if ($exitCode !== 0) {
            throw new \RuntimeException(
                "PDF conversion failed: " . implode("\n", $output)
            );
        }

        // Собираем список созданных файлов
        $files = [];
        for ($i = 1; $i <= $maxPages; $i++) {
            $file = sprintf("{$outputDir}/page_%03d.{$format}", $i);
            if (file_exists($file)) {
                $files[] = $file;
            }
        }

        return $files;
    }

    public function docxToPdf(string $docxPath, string $outputDir): string
    {
        @mkdir($outputDir, 0755, true);
        $profileDir = sys_get_temp_dir() . '/lo_profile_' . Str::random(8);
        @mkdir($profileDir, 0755, true);

        $cmd = implode(' ', [
            'libreoffice',
            '--headless',
            "--env:UserInstallation=" . escapeshellarg("file://{$profileDir}"),
            '--convert-to pdf',
            '--outdir ' . escapeshellarg($outputDir),
            escapeshellarg($docxPath),
            '2>&1',
        ]);
        exec($cmd, $output, $exitCode);

        // Удаляем временный профиль
        $this->rmdir($profileDir);

        if ($exitCode !== 0) {
            throw new \RuntimeException(
                "DOCX to PDF failed: " . implode("\n", $output)
            );
        }

        $outputFile = $outputDir . '/' . pathinfo($docxPath, PATHINFO_FILENAME) . '.pdf';
        if (!file_exists($outputFile)) {
            throw new \RuntimeException("Output PDF not found after conversion");
        }

        return $outputFile;
    }

    public function getPdfPageCount(string $path): int
    {
        $cmd = "pdfinfo " . escapeshellarg($path) . " 2>/dev/null | grep 'Pages:' | awk '{print $2}'";
        $output = shell_exec($cmd);
        return max(1, (int) trim($output ?? '1'));
    }

    private function rmdir(string $dir): void
    {
        if (!is_dir($dir)) return;
        $items = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS),
            \RecursiveIteratorIterator::CHILD_FIRST
        );
        foreach ($items as $item) {
            $item->isDir() ? rmdir($item->getRealPath()) : unlink($item->getRealPath());
        }
        rmdir($dir);
    }
}

Таблица типовых таймингов конвертации

Размер файла PDF→JPEG (1 стр, 150 DPI) DOCX→PDF
< 1 MB 0.3 сек 1.5 сек
1–10 MB 1.2 сек 3.5 сек
> 10 MB 3.5 сек 7 сек

Что входит в настройку серверной конвертации?

  • Развёртывание и настройка Ghostscript/LibreOffice на сервере.
  • Разработка сервиса-обёртки с отказоустойчивостью (обработка ошибок, очистка временных профилей).
  • Настройка очередей (Jobs) для фоновой обработки.
  • Интеграция с вашим приложением (REST API или событий).
  • Документация по API и эксплуатации.
  • Обучение команды (1 час вебинара).

Процесс работы

  1. Анализ — изучаем поток загрузок, замеряем нагрузку.
  2. Проектирование — выбираем инструменты, настраиваем окружение.
  3. Разработка — пишем сервис конвертации, jobs, эндпоинты.
  4. Тестирование — нагрузочное (минимально 1000 файлов).
  5. Деплой и мониторинг — настройка оповещений при ошибках.

Сроки и гарантии

Настройка базовой конвертации — от 2 до 5 дней в зависимости от сложности интеграции. Мы гарантируем стабильную работу при нагрузке до 5000 файлов в день. Наш опыт: более 5 лет на рынке, 200+ проектов с документооборотом. Получите консультацию по настройке конвертации — наши инженеры помогут подобрать оптимальную конфигурацию под вашу нагрузку. Свяжитесь с нами — оценим вашу задачу в течение дня.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060