Плагин конвертера
Преобразование документов в 45 целевых форматов
Плагин Converter превращает Doconut в сервис конвертации документов. Он предоставляет движок, стоящий за публичным фасадом DocumentConverter, и — при желании — готовый к использованию виджет со своим HTTP‑контрактом, так что вы можете конвертировать документы из C#, из виджета или из собственного фронтенда.
Установить пакет
Установите последнюю стабильную версию плагина Converter:
dotnet add package Doconut.NETStandard.ConverterЧтобы зафиксировать плагин на текущем выпуске 26.8.0, укажите версию отдельно:
dotnet add package Doconut.NETStandard.Converter --version 26.8.0Поддерживайте пакет Converter той же версии, что и Doconut.NETStandard. Идентификатор пакета — Doconut.NETStandard.Converter; .26.8.0 встречается только в имени загруженного файла .nupkg.
Регистрация плагина
Метода AddConverter() не существует — модель плагинов Doconut единообразна. Каждый плагин, включая Converter, регистрируется одинаково: вызовите AddPlugin<TPlugin>() внутри AddDoconut(). ConverterPlugin поставляется в собственном пакете NuGet, Doconut.NETStandard.Converter, установленном рядом с базовым пакетом просмотрщика.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Этот вызов бросает исключение при запуске из‑за отсутствующей лицензии, устаревшего файла
TRIALили непостоянной лицензии, не предоставляющей возможностьConverter—InvalidOperationException, возникший внутриAddDoconut(), до того как приложение начнёт обслуживать запросы. Принимаются временные регистрации Demo/NFR; после истечения их срока действия конвертация остаётся доступной, но с водяным знаком на выводе. Бесплатного «тихого» уровня нет. См. Настройка лицензии для информации о загрузке лицензий.
Конвертация из C#
Каждая конвертация возвращает перемещаемый MemoryStream, позиционированный на 0, готовый к чтению или копированию сразу. Получите DocumentConverter из DI там, где он нужен — он без состояния по дизайну, поэтому один экземпляр безопасно переиспользовать между запросами.
viewer.Converter.GetConverter() здесь не существует. Конвертация больше не достигается через экземпляр просмотрщика: вместо этого внедрите Doconut.DocumentConverter.
// Внедрите DocumentConverter; его конструктор internal, поэтому никогда не `new` его.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// sourceExtension включает ведущую точку. password равен null, если только документ не защищён.
Stream png = await converter.ConvertAsync(stream, ".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) в виде потока, как и любой другой результат конвертации.
Целевые форматы
ConversionTarget (пространство имён Doconut.Configs.Conversion) содержит 45 членов:
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, Webp, Msg, Eml, Emlx, Mhtml,
Xlsm, Xlsb, Ppt, Docm, Dot, Dotx, Dotm, Vsdx, Vssx, Vstx, Vsdm, Vssm, Vstm,
Vdx, Vsx, Vtx, IcoЭтот один enum охватывает все семейства источников. В предыдущей библиотеке был тип *ConfigConverter для каждого семейства — WordConfigConverter, ExcelConfigConverter и т.д. — каждый со своим вложенным enum EnTargetFormat, плюс enum SourceFormatConverter для входных данных. Всё это исчезло; см. руководство по миграции.
Не каждый источник конвертируется во каждый целевой формат — плагин сопоставляет каждое семейство форматов источника (Word, Excel, PowerPoint, PDF, CAD, Image, Email, Diagram, Project/Task, PSD, веб‑документ) со своим фиксированным набором разрешённых целей. Не жёстко кодируйте этот 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 | те же поля, что и в ответе выполнения, плюс запрошенный target |
onDownload({ downloadName, downloadToken }) | Пользователь нажимает ссылку Скачать | срабатывает вместе с нативной загрузкой браузера — не перехватывает и не заменяет её |
onError({ phase, message }) | Запрос open или run завершился ошибкой | phase является 'open' или 'run'; message — это очищенная ошибка сервера (или сообщение клиентской стороны для предварительной проверки размера загрузки) |
Doconut.convert() возвращает сам экземпляр виджета — сохраните его, чтобы управлять виджетом программно:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // возврат к экрану idle/drop; не повторно вызывает onReady
conv.loadFile(file); // запускает поток с объектом File; ничего не делает, если сейчас не idle
conv.destroy(); // удаляет слушатели, очищает mount; экземпляр непригоден после этогоСоздайте собственный интерфейс
Виджет — это лишь клиент для этого HTTP‑контракта — создайте собственный интерфейс напрямую для другого пользовательского опыта. Все три маршрута находятся под веткой ASP.NET, где монтируется UseDoconut() (обычно /doconut):
| Маршрут | Назначение | Ответ при успехе |
|---|---|---|
POST ?convert=open (multipart, field 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 — file bytes, 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 | Неизвестный или истёкший токен загрузки | только статус |
Владение ресурсом
Конвертер возвращает позиционируемый в ноль MemoryStream. Вызывающая сторона владеет этим потоком и должна освободить его после копирования или возврата его содержимого. Сервис DocumentConverter сам по себе без состояния и разрешается через внедрение зависимостей; не создавайте и не освобождайте сервис вручную.
Для веб‑виджета загрузочные и скачиваемые хранилища имеют независимые 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, которое он возвращает. Интеграцию можно построить и протестировать от начала до конца на оценочной лицензии до покупки — меняются только байты вывода.
Была ли эта страница полезной?