Plugin de conversión
Convertir documentos a 45 formatos de destino
El plugin Converter convierte Doconut en un servicio de conversión de documentos. Contribuye con el motor detrás de la fachada pública DocumentConverter, y — opcionalmente — un widget listo para usar con su propio contrato HTTP, de modo que pueda convertir documentos desde C#, desde el widget, o desde un frontend que usted mismo escriba.
Instalar el paquete
Instale el último plugin Converter estable:
dotnet add package Doconut.NETStandard.ConverterPara fijar el plugin a la versión actual 26.8.0, pase la versión por separado:
dotnet add package Doconut.NETStandard.Converter --version 26.8.0Mantenga el paquete Converter en la misma versión que Doconut.NETStandard. El ID del paquete es
Doconut.NETStandard.Converter; .26.8.0 aparece solo en el nombre de archivo descargado .nupkg.
Registrar el plugin
No existe un método AddConverter() — el modelo de plugins de Doconut es uniforme. Cada plugin, incluido Converter, se registra de la misma manera: llame a AddPlugin<TPlugin>() dentro de AddDoconut(). ConverterPlugin se entrega en su propio paquete NuGet, Doconut.NETStandard.Converter, instalado junto al paquete base del visor.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Esta llamada lanza una excepción al iniciar si falta una licencia, si hay un archivo legado
TRIAL, o si una licencia no temporal no otorga la capacidadConverter— unInvalidOperationExceptiongenerado desde dentro deAddDoconut(), antes de que la aplicación sirva solicitudes. Se aceptan registros temporales Demo/NFR; después de su vencimiento calendario, la conversión sigue disponible con salida con marca de agua. No hay un nivel gratuito silencioso. Consulte Configuración de licencia para saber cómo se cargan las licencias.
Convertir desde C#
Cada conversión devuelve un MemoryStream buscable posicionado en 0, listo para leer o copiar inmediatamente. Resuelva DocumentConverter desde DI donde lo necesite — es sin estado por diseño, por lo que una única instancia es segura para reutilizarse en múltiples solicitudes.
viewer.Converter.GetConverter() no existe aquí. La conversión ya no se accede a través de la instancia del visor: inyecte Doconut.DocumentConverter en su lugar.
// Inyecta DocumentConverter; su constructor es interno, así que nunca lo `new`.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// sourceExtension incluye el punto inicial. password es null a menos que el documento esté protegido.
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);Dos detalles que es fácil equivocarse: sourceExtension en la sobrecarga de stream debe incluir el punto inicial (".xlsx", no "xlsx") — el conversor lo compara con el catálogo de formatos y una extensión sin punto no se resolverá. Y a pesar de su nombre, WordToHtmlAsync devuelve Task<Stream>, no Task<string> — obtiene el documento HTML (imágenes incrustadas como Base64) como un stream, igual que cualquier otro resultado de conversión.
Formatos de destino
ConversionTarget (espacio de nombres Doconut.Configs.Conversion) tiene 45 miembros:
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, IcoEste enum cubre cada familia de origen. La biblioteca anterior tenía un tipo *ConfigConverter por familia — WordConfigConverter, ExcelConfigConverter, etc. — cada uno con su propio enum anidado EnTargetFormat, además de un enum SourceFormatConverter para la entrada. Todos han desaparecido; consulte la guía de migración.
No todos los orígenes se convierten a todos los destinos — el plugin asigna cada familia de formato de origen (Word, Excel, PowerPoint, PDF, CAD, Imagen, Correo electrónico, Diagrama, Proyecto/Tarea, PSD, documento web) a su propio conjunto fijo de destinos permitidos. No codifique este enum como la lista de destinos de su UI: ?convert=open devuelve el allowedTargets real para el archivo que se acaba de subir, y eso es lo que debe impulsar un selector.
Widget incrustable
Los endpoints ?convert=open|run|download del widget son opcionales y están deshabilitados por defecto — seguros por defecto. Habilítalos del lado del servidor, junto con el registro del plugin:
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>Sin AddConverterWidget(), los tres endpoints ?convert= responden 404 — pero el archivo JS sigue sirviéndose de todos modos (es un recurso estático incrustado simple; solo los endpoints a los que se comunica están restringidos). AddConverterWidget() aún requiere que el plugin Converter esté registrado y una licencia que conceda Converter — no otorga derechos de conversión por sí solo.
Personaliza el widget
Opciones de inicialización pasadas a Doconut.convert(selector, options):
| Opción | Tipo | Predeterminado | Notas |
|---|---|---|---|
basePath | string | /doconut | Ruta base para los endpoints ?convert=; debe coincidir con la rama ASP.NET donde UseDoconut() está realmente montado (normalmente coordinado a través de MiddlewarePath) |
resPath | string | /doconut-res | Aceptado para mantener la consistencia de configuración con otros widgets Doconut; el widget conversor actualmente no genera ninguna URL a partir de él |
maxUploadMb | number | 25 | Solo verificación previa del lado del cliente — rechaza un archivo demasiado grande antes de subirlo. El servidor impone su propio límite de forma independiente y responde 413 si se supera |
licenseUrl | string | null | null | Cuando se establece, convierte el aviso de marca de agua en la pantalla de resultados en un enlace a esta URL |
labels | object | {} | Sobrescribe cualquier subconjunto de las cadenas predeterminadas en inglés del widget (texto de arrastre, botones, anuncios aria‑live, mensajes de error) |
Callbacks:
| Callback | Se dispara cuando | Carga |
|---|---|---|
onReady() | El widget ha renderizado su pantalla idle/drop | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open tiene éxito | token de sesión de origen, recuento de páginas, extensión de origen (sin punto inicial), lista de destinos permitidos |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run tiene éxito | los mismos campos que la respuesta de ejecución, más el target solicitado |
onDownload({ downloadName, downloadToken }) | El usuario hace clic en el enlace Descargar | se dispara junto con la descarga nativa del navegador — no la intercepta ni la reemplaza |
onError({ phase, message }) | Una solicitud de apertura o ejecución falla | phase es 'open' o 'run'; message es el error del servidor sanitizado (o un mensaje del lado del cliente para la verificación previa del tamaño de carga) |
Doconut.convert() devuelve la propia instancia del widget — mantenla para controlar el widget programáticamente:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // volver a la pantalla de inactividad/soltar; no vuelve a disparar onReady
conv.loadFile(file); // inicia el flujo con un objeto File; no hace nada a menos que esté inactivo
conv.destroy(); // elimina los listeners, vacía el mount; la instancia no es reutilizable después de estoConstruye tu propio frontend
El widget es solo un cliente para este contrato HTTP — construye tu propio frontend directamente contra él para una UX diferente. Las tres rutas se encuentran bajo la rama ASP.NET donde UseDoconut() está montado (normalmente /doconut):
| Ruta | Propósito | Respuesta de éxito |
|---|---|---|
POST ?convert=open (multipart, field file) | Subir y abrir un documento fuente para vista previa | 200 — { token, pages, sourceExt, allowedTargets } |
POST ?token=<token>&convert=run&target=<ext> | Convertir la fuente almacenada a target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET ?convert=download&token=<downloadToken> | Transmitir el archivo convertido | 200 — bytes del archivo, Content-Disposition: attachment, Cache-Control: no-store |
Los bytes de la fuente subidos se almacenan del lado del servidor con un TTL de 30 minutos; una vez que esa ventana expira, run responde 404 y el archivo debe volver a abrirse. El resultado convertido vive en el mismo almacén — downloadToken obtiene su propia ventana fresca de 30 minutos cuando la conversión se completa — mientras que resultToken es un token de sesión de visor ordinario cuyo tiempo de vida sigue la caché de sesión del visor, independiente del almacén.
sourceExt en la respuesta open no tiene punto inicial (p. ej. "docx") — la convención opuesta al parámetro sourceExtension en DocumentConverter.ConvertAsync, que requiere uno.
Modos de falla, agrupados por ruta:
| Ruta | Estado | Cuándo | Cuerpo |
|---|---|---|---|
| cualquiera | 404 | El widget no está habilitado (AddConverterWidget() nunca fue llamado) — verificado antes de que cualquiera de las tres rutas se despache | solo estado |
| cualquiera | 405 | Verbo HTTP incorrecto (open/run requieren POST; download requiere GET) | solo estado |
open | 413 | El archivo subido supera MaxUploadMb | { "error": "File is too large." } |
open | 400 | Sin cuerpo multipart, sin archivo, o una extensión de origen que no se puede convertir | { "error": "..." } |
run | 400 | Token malformado (no es un GUID), o un target que no se analiza a un ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target no está en el allowedTargets de la fuente | { "error": "That target format is not available for this file." } |
run | 404 | La carga almacenada ha expirado (TTL de 30 minutos) o el token nunca se abrió | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | El procesamiento falló internamente | { "error": "<sanitized message>" } — sanitizado de la misma manera que cualquier otra ruta de error Doconut; nunca revela nombres internos del motor |
download | 400 | Token malformado (no es un GUID) | solo estado |
download | 404 | Token de descarga desconocido o expirado | solo estado |
Propiedad del recurso
El convertidor devuelve un MemoryStream buscable posicionado en cero. El llamador posee ese flujo y debe disponerlo después de copiar o devolver su contenido. El servicio DocumentConverter en sí es sin estado y se resuelve mediante inyección de dependencias; no lo construya ni lo disponga manualmente.
Para el widget web, los almacenes de carga y descarga tienen TTLs independientes de 30 minutos. Un resultToken de visualizador sigue la duración de la sesión del visualizador en su lugar. Cerrar un resultado de visualizador no elimina un almacén de descarga aún válido, y restablecer el widget del navegador no extiende ninguno de los TTL.
Solución de problemas
| Síntoma | Verificación |
|---|---|
Resolver DocumentConverter falla | El registro de ConverterPlugin ocurrió dentro de AddDoconut() |
| La aplicación falla durante el inicio | La licencia cargada otorga Converter |
| La conversión de flujo indica que el formato no es compatible | sourceExtension incluye el punto inicial |
| El JavaScript del widget se carga pero las solicitudes devuelven 404 | AddConverterWidget() no fue llamado |
| Las solicitudes del widget usan la URL incorrecta | basePath coincide con la rama donde UseDoconut() está mapeado |
| Falta el objetivo | Use allowedTargets devuelto por convert=open; no todas las fuentes admiten cada objetivo de enumeración |
| La descarga expiró | Repita convert=open/convert=run; los tokens de almacén son intencionalmente temporales |
Marca de agua
Con ConverterPlugin registrado, la licencia del host está en uno de tres estados:
| Estado de la licencia | Control de inicio | Salida de conversión |
|---|---|---|
Licencia de visualizador pagada que otorga Converter, dentro de su período de validez | Pasa | Limpio — watermarked: false |
| Licencia de evaluación activa (demo/NFR) | Pasa | Convierte con éxito, marcado con la marca de agua de evaluación — watermarked: true |
Sin licencia, un archivo legacy TRIAL, o una licencia no temporal que no otorga Converter | La aplicación nunca inicia — la puerta de inicio descrita arriba lanza una excepción | — |
| Licencia temporal/demo expirada | El registro sobrevive a la expiración | Convierte con la marca de agua de evaluación — watermarked: true |
Ambas rutas de llamada calculan la bandera a partir de la misma regla: la fachada C# DocumentConverter la deriva internamente del IsViewerLicensed y el estado IsTemporary de la licencia, y el controlador ?convert=run del widget realiza la comprobación equivalente (IsViewerLicensed && !IsTrial && !IsTemporary) para rellenar el campo watermarked que devuelve. Se puede crear y probar una integración de extremo a extremo con una licencia de evaluación antes de la compra — solo cambian los bytes de salida.
¿Fue útil esta página?