Плагин Конвертера
Преобразуйте документы в 24 целевых формата
Плагин Converter превращает Doconut в сервис конвертации документов. Он предоставляет движок, лежащий в основе публичного фасада DocumentConverter, и — при включении — готовый к использованию виджет со своим HTTP‑контрактом, так что вы можете конвертировать документы из C#, из виджета или из собственного фронтенда.
Установить пакет
Установите последнюю стабильную версию плагина Converter:
dotnet add package Doconut.NET6.ConverterЧтобы закрепить плагин за текущим выпуском 26.7.0, укажите версию отдельно:
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, установленном рядом с базовым пакетом просмотрщика.
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 в любом месте, где он нужен — он без состояния, поэтому один экземпляр безопасно переиспользовать между запросами.
// 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 |
Исходные байты сохраняются на сервере со сроком жизни 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 | Неизвестный или истёкший токен скачивания | только статус |
Владение ресурсами
Конвертер возвращает позиционированный в 0 seekable MemoryStream. Владелец — вызывающий код; после копирования или возврата содержимого поток следует освободить. Сервис DocumentConverter сам по себе без состояния и извлекается из DI; не создавайте и не освобождайте его вручную.
Для веб‑виджета «кладовые» загрузки и скачивания имеют независимые TTL 30 минут. Токен resultToken просмотрщика живёт столько, сколько живёт сессия просмотрщика. Закрытие результата в просмотрщике не удаляет ещё действующую «кладовую» скачивания, а сброс виджета в браузере не продлевает ни один из TTL.
Устранение неполадок
| Признак | Проверка |
|---|---|
Не удаётся разрешить DocumentConverter | Регистрация ConverterPlugin выполнена внутри AddDoconut() |
| Приложение падает при старте | Загруженная лицензия предоставляет Converter |
| При конвертации поток сообщает, что формат не поддерживается | sourceExtension содержит ведущую точку |
| JavaScript виджета загружается, но запросы возвращают 404 | AddConverterWidget() не был вызван |
| Запросы виджета используют неверный URL | basePath совпадает с веткой, где смонтирован 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 в ответе. Интеграцию можно собрать и протестировать «сквозным» способом на оценочной лицензии до покупки — меняются только байты вывода.
Была ли эта страница полезной?