dxpdf
Быстрый автономный конвертер DOCX в PDF, написанный на Rust и использующий Skia — без Microsoft Office, LibreOffice или облачных API. Доступен как CLI-инструмент, Rust-библиотека и Python-пакет.
Проблема
Конвертация документов Word в PDF — одна из самых распространённых задач в бизнес-софте. Счета, договоры, отчёты, формы соответствия — они начинаются как .docx-файлы и должны стать PDF для обмена, архивирования или печати.
Существующие решения имеют значительные компромиссы:
- Microsoft Office / LibreOffice — требует установки полного офисного пакета на каждый сервер. Headless-режим LibreOffice медленный, потребляет много памяти и даёт непоследовательные результаты между версиями. Масштабирование означает запуск нескольких экземпляров, потребляющих гигабайты оперативной памяти.
- Облачные API (Google Docs, Adobe, CloudConvert) — добавляют задержку, плату за каждую конвертацию и отправку потенциально конфиденциальных документов на сторонние серверы. Неприемлемо для регулируемых отраслей или изолированных сред.
- Инструменты HTML-to-PDF (wkhtmltopdf, Puppeteer) — требуют предварительного преобразования DOCX в HTML с потерей точности форматирования. Таблицы, колонтитулы и разрывы страниц редко переживают обратный путь.
Ни одно из этих решений не работает хорошо, когда нужна быстрая, точная, офлайн-конвертация в масштабе — особенно в автоматизированных пайплайнах, CI/CD-системах или встраиваемых приложениях, где установка LibreOffice невозможна.
Как dxpdf решает эту задачу
dxpdf — это автономный конвертер DOCX в PDF, написанный на Rust и использующий графическую библиотеку Google Skia. Он читает .docx-файлы напрямую, парсит OOXML-структуру и рендерит PDF с пиксельной точностью — всё в одном бинарнике без внешних зависимостей кроме Skia.
Вдохновлённый Flutter пайплайн measure-layout-paint обеспечивает соответствие переноса текста, размеров таблиц и разрывов страниц тому, что производит Microsoft Word:
DOCX (ZIP) → Парсинг → Модель документа → Измерение → Вёрстка → Отрисовка → PDF
Результат — конвертер, который выполняет работу за ~115 мс на 3-страничном документе с таблицами и изображениями, используя всего 19 МБ памяти — достаточно быстро для запуска внутри обработчика запросов или пакетной обработки тысяч документов.
Возможности
dxpdf реализует 34 функции OOXML с полным покрытием, включая:
- Форматирование текста — жирный, курсив, подчёркивание, размер шрифта, гарнитура, цвет, межсимвольный интервал, надстрочный и подстрочный текст, заливка символов
- Абзацы — выравнивание (по левому краю, по центру, по правому краю), интервалы, отступы, табуляция, границы, заливка
- Таблицы — ширина столбцов, отступы ячеек с 3-уровневым каскадированием, объединённые ячейки (горизонтальное и вертикальное), высота строк, границы, заливка ячеек, вложенные таблицы
- Изображения — встроенные (PNG, JPEG, BMP, WebP) и плавающие/привязанные с выравниванием и процентным позиционированием
- Стили — стили абзацев и символов с наследованием
basedOn, настройки документа по умолчанию, шрифты темы - Колонтитулы — текст, изображения, номера страниц (коды полей PAGE/NUMPAGES)
- Списки — маркированные, десятичные, строчные/прописные буквы, строчные/прописные римские с отслеживанием счётчиков
- Гиперссылки — отображаются как кликабельные PDF-аннотации ссылок
- Разделы — несколько размеров страниц и полей, разрывы разделов, книжная и альбомная ориентация
- Вёрстка — автоматическая пагинация, перенос слов, режимы межстрочного интервала, обтекание плавающих изображений
Три способа использования
Инструмент командной строки
Установите и запустите одной командой:
cargo install dxpdf
dxpdf input.docx -o output.pdf
Rust-библиотека
Один вызов функции — байты на вход, байты на выход:
let docx_bytes = std::fs::read("document.docx")?;
let pdf_bytes = dxpdf::convert(&docx_bytes)?;
std::fs::write("output.pdf", &pdf_bytes)?;
Для большего контроля можно просмотреть модель документа перед рендерингом:
use dxpdf::{parse, model};
let document = parse::parse(&std::fs::read("document.docx")?)?;
for block in &document.blocks {
match block {
model::Block::Paragraph(p) => { /* inspect paragraph */ }
model::Block::Table(t) => { /* inspect table */ }
}
}
let pdf_bytes = dxpdf::convert_document(&document)?;
Python-пакет
Установите с PyPI и используйте в любом Python-приложении:
pip install dxpdf
import dxpdf
# Байты на вход, байты на выход
pdf_bytes = dxpdf.convert(open("input.docx", "rb").read())
# Файл в файл
dxpdf.convert_file("input.docx", "output.pdf")
Производительность
Бенчмарк на Apple M3 Max с hyperfine (20 запусков, 3 прогревочных), конвертация 3-страничного документа с 11 таблицами, 2 изображениями и 2 разделами:
| Метрика | Значение |
|---|---|
| Среднее время конвертации | 113 мс |
| Пиковая память (RSS) | 19 МБ |
Ядро на Rust содержит 104 модульных теста и 9 интеграционных тестов, включая визуальные регрессионные тесты, сравнивающие отрендеренные PDF с эталонными документами, сгенерированными Word.
Сценарии использования
Автоматизированные пайплайны документов
CI/CD-системы или пакетные процессоры, генерирующие договоры, счета или отчёты из .docx-шаблонов. dxpdf запускается как один бинарник — без установки LibreOffice, без Docker-образа с полным десктопным окружением, без стоимости за каждый документ.
Регулируемые среды
Приложения в здравоохранении, юриспруденции и финансах, где документы не могут покидать сеть. dxpdf работает полностью офлайн без внешних вызовов, что делает его подходящим для изолированных и локальных развёртываний.
Встраиваемые системы и edge-вычисления
IoT-устройства, киоски или лёгкие контейнеры, где установка офисного пакета на 500 МБ нецелесообразна. Потребление памяти dxpdf в 19 МБ и субсекундное время конвертации делают его жизнеспособным для сред с ограниченными ресурсами.
Python веб-приложения
Бэкенды на Django, Flask или FastAPI, которым нужно конвертировать загруженные DOCX-файлы на лету. Python-обёртки оборачивают Rust-ядро через PyO3, обеспечивая нативную производительность без подпроцессов или внешних сервисов.
Нет. dxpdf — это автономный конвертер, который читает DOCX-файлы напрямую и рендерит PDF с помощью графического движка Google Skia. У него нет зависимости от какого-либо офисного пакета.
Топ контрибьюторов
thenixan
Информация о репозитории
- Стек технологий
- RustPython
- Версия
- v0.1.4
- Лицензия
- MIT
- Контрибьютор
- 1
- Последнее изменение
- 21 мар. 2026 г.