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

Преобразуйте документы в 24 целевых формата

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

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

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

bash
dotnet add package Doconut.NET6.Converter

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

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

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

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

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

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

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

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

Каждая конвертация возвращает позиционированный в 0 seekable MemoryStream, готовый к чтению или копированию сразу. Получайте 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 или run завершился ошибкойphase — '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

Исходные байты сохраняются на сервере со сроком жизни 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Неизвестный или истёкший токен скачиваниятолько статус

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

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

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

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

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

Водяные знаки

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

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

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

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