Плагин Конвертера
Конвертировать документы в 24 целевых формата
Плагин Converter превращает Doconut в сервис конвертации документов. Он обеспечивает движок, лежащий в основе публичного фасада DocumentConverter, и — при включении — готовый к использованию виджет со своим HTTP‑контрактом, так что вы можете конвертировать документы из C#, из виджета или из собственного фронтенда.
Установить пакет
Установите последнюю стабильную версию плагина Converter:
dotnet add package Doconut.NET8.ConverterЧтобы зафиксировать плагин на текущем выпуске 26.7.0, укажите версию отдельно:
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, установленном рядом с базовым пакетом просмотрщика.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Этот вызов бросает исключение при запуске, если отсутствует лицензия, присутствует устаревший файл
TRIALили лицензия не является временной и не предоставляет возможностьConverter—InvalidOperationException, возникшее внутриAddDoconut()до того, как приложение начнёт обслуживать запросы. Принимаются временные демо/НФР‑регистрации; после их истечения конвертация остаётся доступной, но с водяным знаком. Бесплатного «тихого» уровня нет. См. Настройка лицензии для информации о загрузке лицензий.
Конвертировать из C#
Каждая конвертация возвращает перемещаемый MemoryStream, позиционированный в 0, готовый к чтению или копированию сразу. Получайте DocumentConverter из DI там, где он нужен — сервис без состояния, поэтому один экземпляр безопасно переиспользовать между запросами.
// Inject DocumentConverter; its constructor is internal, so never `new` it.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// 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);Stream html = await converter.WordToHtmlAsync("report.docx", ct);Stream docx = await converter.HtmlToWordAsync(html, ConversionTarget.Docx, ct);Две детали, которые легко перепутать: параметр sourceExtension в перегрузке со стримом должен включать ведущую точку (".xlsx", а не "xlsx"), иначе конвертер не найдёт соответствие в каталоге форматов. И, несмотря на название, WordToHtmlAsync возвращает Task<Stream>, а не Task<string> — вы получаете HTML‑документ (изображения встроены как Base64) в виде потока, как и любой другой результат конвертации.
Целевые форматы
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 являются опциональными и по умолчанию отключены — безопасно из коробки. Включите их на сервере вместе с регистрацией плагина:
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
options.AddConverterWidget(widget =>
{
widget.MaxUploadMb = 25;
});
});<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):
| Параметр | Тип | По умолчанию | Примечания |
|---|---|---|---|
basePath | string | /doconut | Базовый путь для эндпоинтов ?convert=; должен совпадать с веткой ASP.NET, где смонтирован UseDoconut() (обычно задаётся через MiddlewarePath) |
resPath | string | /doconut-res | Оставлен для согласованности с другими виджетами Doconut; текущий виджет конвертера не формирует URL из этого параметра |
maxUploadMb | number | 25 | Только клиентская проверка — отклоняет слишком большой файл до загрузки. Сервер независимо ограничивает размер и отвечает 413, если превышен лимит |
licenseUrl | string | null | null | При указании превращает уведомление о водяном знаке на экране результата в ссылку на указанный URL |
labels | object | {} | Переопределяет любые подмножества английских строк виджета (текст подсказки, кнопки, 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() возвращает сам объект виджета — сохраняйте его, если хотите управлять виджетом программно:
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> | Конвертация сохранённого источника в target | 200 — { 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) | только статус |
open | 413 | Размер загружаемого файла превышает MaxUploadMb | { "error": "File is too large." } |
open | 400 | Нет multipart‑тела, нет файла или расширение источника не поддерживается | { "error": "..." } |
run | 400 | Некорректный токен (не GUID) или target, который не распознаётся как ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target отсутствует в allowedTargets источника | { "error": "That target format is not available for this file." } |
run | 404 | Сохранённый загрузкой файл истёк (TTL 30 мин) или токен никогда не открывался | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | Внутренняя ошибка обработки | { "error": "<sanitized message>" } — очищается так же, как любые другие сообщения об ошибках Doconut; внутренние названия движка не раскрываются |
download | 400 | Некорректный токен (не GUID) | только статус |
download | 404 | Неизвестный или истёкший токен загрузки | только статус |
Владение ресурсами
Конвертер возвращает перемещаемый MemoryStream, позиционированный в 0. Вызывающая сторона владеет этим потоком и должна освободить его после копирования или возврата содержимого. Сервис DocumentConverter сам по себе без состояния и получаем из DI; не создавайте и не освобождайте его вручную.
Для веб‑виджета хранилища загрузок и загрузок результатов имеют независимый TTL 30 минут. Токен resultToken привязан к сроку жизни сессии просмотрщика. Закрытие результата в просмотрщике не удаляет всё ещё действующее хранилище загрузки, а сброс виджета в браузере не продлевает ни один из TTL.
Устранение неполадок
| Симптом | Проверка |
|---|---|
Не удаётся получить DocumentConverter | Регистрация ConverterPlugin выполнена внутри AddDoconut() |
| Приложение падает при старте | Загруженная лицензия предоставляет Converter |
| При конвертации поток сообщает, что формат не поддерживается | sourceExtension содержит ведущую точку |
| JavaScript виджета загружается, но запросы возвращают 404 | AddConverterWidget() не был вызван |
| Запросы виджета используют неверный URL | basePath совпадает с веткой, где смонтирован 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 в ответе. Интеграцию можно собрать и протестировать «от конца до конца» на оценочной лицензии перед покупкой — меняются только байты вывода.
Была ли эта страница полезной?