Плагин Конвертера

Конвертировать документы в 24 целевых формата

Плагин Converter превращает Doconut в сервис конвертации документов. Он обеспечивает движок, лежащий в основе публичного фасада DocumentConverter, и — при включении — готовый к использованию виджет со своим HTTP‑контрактом, так что вы можете конвертировать документы из C#, из виджета или из собственного фронтенда.

Установить пакет

Установите последнюю стабильную версию плагина Converter:

bash
dotnet add package Doconut.NET8.Converter

Чтобы зафиксировать плагин на текущем выпуске 26.7.0, укажите версию отдельно:

bash
dotnet add package Doconut.NET8.Converter --version 26.7.0

Держите пакет Converter той же версии, что и Doconut.NET8. Идентификатор пакета — Doconut.NET8.Converter; суффикс .26.7.0 присутствует только в имени загруженного файла .nupkg.

Зарегистрировать плагин

Метода AddConverter() нет — модель плагинов Doconut единообразна. Каждый плагин, включая Converter, регистрируется одинаково: вызывайте AddPlugin<TPlugin>() внутри AddDoconut(). ConverterPlugin поставляется в собственном NuGet‑пакете Doconut.NET8.Converter, установленном рядом с базовым пакетом просмотрщика.

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});

Этот вызов бросает исключение при запуске, если отсутствует лицензия, присутствует устаревший файл TRIAL или лицензия не является временной и не предоставляет возможность Converter — InvalidOperationException, возникшее внутри AddDoconut() до того, как приложение начнёт обслуживать запросы. Принимаются временные демо/НФР‑регистрации; после их истечения конвертация остаётся доступной, но с водяным знаком. Бесплатного «тихого» уровня нет. См. Настройка лицензии для информации о загрузке лицензий.

Конвертировать из C#

Каждая конвертация возвращает перемещаемый MemoryStream, позиционированный в 0, готовый к чтению или копированию сразу. Получайте DocumentConverter из DI там, где он нужен — сервис без состояния, поэтому один экземпляр безопасно переиспользовать между запросами.

csharp
// Inject DocumentConverter; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);
csharp
// sourceExtension includes the leading dot. password is null unless the document is protected.
Stream png = await converter.ConvertAsync(upload, ".xlsx", ConversionTarget.Png, password: null, ct: ct);
csharp
Stream html = await converter.WordToHtmlAsync("report.docx", ct);
csharp
Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);

Две детали, которые легко перепутать: параметр sourceExtension в перегрузке со стримом должен включать ведущую точку (".xlsx", а не "xlsx"), иначе конвертер не найдёт соответствие в каталоге форматов. И, несмотря на название, WordToHtmlAsync возвращает Task<Stream>, а не Task<string> — вы получаете HTML‑документ (изображения встроены как Base64) в виде потока, как и любой другой результат конвертации.

Целевые форматы

text
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, Webp

Не каждый исходный формат конвертируется во все целевые — плагин сопоставляет семейство формата источника (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project/Task, PSD, web document) со своим фиксированным набором разрешённых целей. Не хардкодьте этот enum в UI: ?convert=open возвращает реальный список allowedTargets для загруженного файла, и именно его следует использовать в выпадающике.

Встроенный виджет

Эндпоинты виджета ?convert=open|run|download являются опциональными и по умолчанию отключены — безопасно из коробки. Включите их на сервере вместе с регистрацией плагина:

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = "Doconut.Viewer.lic";
    options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
    options.AddConverterWidget(widget =>
    {
        widget.MaxUploadMb = 25;
    });
});
html
<div id="doconut-convert"></div>
<script src="/doconut-res/js/doconutConverter.js"></script>
<script>
  Doconut.convert('#doconut-convert', { basePath: '/doconut', resPath: '/doconut-res', maxUploadMb: 25 });
</script>

Без вызова AddConverterWidget() три эндпоинта ?convert= отвечают 404 — но сам JS‑файл всё равно отдается (это обычный встроенный статический ресурс; только эндпоинты, к которым он обращается, защищены). AddConverterWidget() всё равно требует, чтобы плагин Converter был зарегистрирован и лицензия предоставляла Converter — он не даёт права на конвертацию сам по себе.

Настроить виджет

Параметры инициализации, передаваемые в Doconut.convert(selector, options):

ПараметрТипПо умолчаниюПримечания
basePathstring/doconutБазовый путь для эндпоинтов ?convert=; должен совпадать с веткой ASP.NET, где смонтирован UseDoconut() (обычно задаётся через MiddlewarePath)
resPathstring/doconut-resОставлен для согласованности с другими виджетами Doconut; текущий виджет конвертера не формирует URL из этого параметра
maxUploadMbnumber25Только клиентская проверка — отклоняет слишком большой файл до загрузки. Сервер независимо ограничивает размер и отвечает 413, если превышен лимит
licenseUrlstring | nullnullПри указании превращает уведомление о водяном знаке на экране результата в ссылку на указанный URL
labelsobject{}Переопределяет любые подмножества английских строк виджета (текст подсказки, кнопки, aria‑live‑сообщения, сообщения об ошибках)

Обратные вызовы:

Обратный вызовСрабатывает когдаДанные
onReady()Виджет отрисовал экран ожидания/заглушки
onSourceLoaded({ token, pages, sourceExt, allowedTargets })?convert=open завершилось успешнотокен сессии источника, количество страниц, расширение источника (без точки), список разрешённых целей
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target })?convert=run завершилось успешноте же поля, что и в ответе run, плюс запрошенная цель target
onDownload({ downloadName, downloadToken })Пользователь нажал ссылку Downloadсрабатывает одновременно с нативным скачиванием браузера — не перехватывает и не заменяет его
onError({ phase, message })Ошибка запроса open или runphase — 'open' или 'run'; message — очищенное сообщение сервера (или клиентское сообщение о проверке размера)

Doconut.convert() возвращает сам объект виджета — сохраняйте его, если хотите управлять виджетом программно:

javascript
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset();         // возврат к экрану ожидания; onReady не вызывается повторно
conv.loadFile(file);  // запускает процесс с объектом File; без действия, если виджет не в состоянии ожидания
conv.destroy();       // удаляет обработчики, очищает монтировку; после этого объект нельзя использовать

Создать собственный фронтенд

Виджет — лишь клиент для этого HTTP‑контракта — вы можете построить собственный фронтенд, напрямую используя его, чтобы получить иной UX. Все три маршрута находятся под веткой ASP.NET, где смонтирован UseDoconut() (обычно /doconut):

МаршрутНазначениеОтвет при успехе
POST ?convert=open (multipart, поле file)Загрузка и открытие исходного документа для предварительного просмотра200 — { token, pages, sourceExt, allowedTargets }
POST ?token=<token>&convert=run&target=<ext>Конвертация сохранённого источника в target200 — { downloadToken, resultToken, resultPages, downloadName, watermarked }
GET ?convert=download&token=<downloadToken>Потоковый вывод сконвертированного файла200 — байты файла, Content-Disposition: attachment, Cache-Control: no-store

Исходные байты сохраняются на сервере с TTL 30 минут; после истечения этого окна запрос run отвечает 404, и файл нужно открыть заново. Конвертированный результат хранится в том же хранилище — downloadToken получает собственное окно в 30 минут после завершения конвертации — тогда как resultToken является обычным токеном сессии просмотрщика и живёт столько, сколько живёт сессия просмотрщика, независимо от хранилища.

sourceExt в ответе open не содержит ведущей точки (например, "docx"), что противоположно конвенции параметра sourceExtension в DocumentConverter.ConvertAsync, где точка обязательна.

Ошибочные режимы, сгруппированные по маршруту

МаршрутСтатусКогдаТело
любой404Виджет не включён (AddConverterWidget() не вызывался) — проверяется до обработки любого из трёх маршрутовтолько статус
любой405Неправильный HTTP‑метод (open/run требуют POST; download — GET)только статус
open413Размер загружаемого файла превышает MaxUploadMb{ "error": "File is too large." }
open400Нет multipart‑тела, нет файла или расширение источника не поддерживается{ "error": "..." }
run400Некорректный токен (не GUID) или target, который не распознаётся как ConversionTarget{ "error": "Invalid token." } / { "error": "Unknown target format." }
run400target отсутствует в allowedTargets источника{ "error": "That target format is not available for this file." }
run404Сохранённый загрузкой файл истёк (TTL 30 мин) или токен никогда не открывался{ "error": "Upload expired — please re-open the file." }
open, run500Внутренняя ошибка обработки{ "error": "<sanitized message>" } — очищается так же, как любые другие сообщения об ошибках Doconut; внутренние названия движка не раскрываются
download400Некорректный токен (не GUID)только статус
download404Неизвестный или истёкший токен загрузкитолько статус

Владение ресурсами

Конвертер возвращает перемещаемый MemoryStream, позиционированный в 0. Вызывающая сторона владеет этим потоком и должна освободить его после копирования или возврата содержимого. Сервис DocumentConverter сам по себе без состояния и получаем из DI; не создавайте и не освобождайте его вручную.

Для веб‑виджета хранилища загрузок и загрузок результатов имеют независимый TTL 30 минут. Токен resultToken привязан к сроку жизни сессии просмотрщика. Закрытие результата в просмотрщике не удаляет всё ещё действующее хранилище загрузки, а сброс виджета в браузере не продлевает ни один из TTL.

Устранение неполадок

СимптомПроверка
Не удаётся получить DocumentConverterРегистрация ConverterPlugin выполнена внутри AddDoconut()
Приложение падает при стартеЗагруженная лицензия предоставляет Converter
При конвертации поток сообщает, что формат не поддерживаетсяsourceExtension содержит ведущую точку
JavaScript виджета загружается, но запросы возвращают 404AddConverterWidget() не был вызван
Запросы виджета используют неверный URLbasePath совпадает с веткой, где смонтирован UseDoconut()
Цель отсутствуетИспользуйте allowedTargets, возвращённый convert=open; не каждый источник поддерживает каждый enum‑целевой формат
Скачивание истеклоПовторите convert=open / convert=run; токены хранилища намеренно временные

Наложение водяного знака

При зарегистрированном ConverterPlugin лицензия хоста может находиться в одном из трёх состояний:

Состояние лицензииПроверка при запускеРезультат конвертации
Платная лицензия просмотрщика, предоставляющая Converter, в пределах срока действияПроходитЧистый — watermarked: false
Активная оценочная (демо/NFR) лицензияПроходитКонвертация проходит, но результат помечен оценочным водяным знаком — watermarked: true
Отсутствие лицензии, устаревший файл TRIAL или нелицензионный файл, не предоставляющий ConverterПриложение не стартует — описанная выше проверка бросает исключение
Истёкшая временная/демо‑лицензияРегистрация сохраняется после истеченияКонвертация проходит с оценочным водяным знаком — watermarked: true

Оба пути вычисляют флаг одинаково: фасад C# DocumentConverter выводит его из состояний лицензии IsViewerLicensed и IsTemporary, а обработчик ?convert=run в виджете делает эквивалентную проверку (IsViewerLicensed && !IsTrial && !IsTemporary), заполняя поле watermarked в ответе. Интеграцию можно собрать и протестировать «от конца до конца» на оценочной лицензии перед покупкой — меняются только байты вывода.

Была ли эта страница полезной?