Плагин Конвертера
Преобразуйте документы в 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(), до того как приложение начнёт обслуживать запросы. Принимаются временные регистрации Demo/NFR; после их календарного истечения конвертация остаётся доступной, но с водяным знаком на выводе. Тихого бесплатного уровня нет. См. Настройка лицензии для информации о загрузке лицензий.
Конвертировать из C#
Каждая конвертация возвращает позиционируемый на 0 seekable MemoryStream, готовый к чтению или копированию сразу. Получите DocumentConverter из DI в любом месте, где он нужен — он без состояния по дизайну, поэтому один экземпляр безопасно переиспользовать между запросами.
// Внедрите DocumentConverter; его конструктор internal, поэтому никогда не `new` его.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// sourceExtension включает ведущую точку. password равно null, если только документ не защищён.
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, веб‑документ) со своим фиксированным набором разрешённых целей. Не захардкодьте этот 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 }) | Пользователь нажимает ссылку 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(); // удаляет слушатели, очищает 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, который требует её.
Сценарии отказов, сгруппированные по маршруту:
| Маршрут | Статус | Когда | Тело |
|---|---|---|---|
| any | 404 | Виджет не включён (AddConverterWidget() никогда не вызывался) — проверяется до обработки любого из трёх маршрутов | статус только |
| any | 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, которое он возвращает. Интеграцию можно собрать и протестировать сквозным способом на оценочной лицензии до покупки — меняются только байты вывода.
Была ли эта страница полезной?