Plugin Conversor
Converter documentos para 24 formatos de destino
O plugin Conversor transforma o Doconut em um serviço de conversão de documentos. Ele fornece o mecanismo por trás da fachada pública DocumentConverter, e — opcionalmente — um widget pronto para uso com seu próprio contrato HTTP, permitindo que você converta documentos a partir de C#, do widget ou de um frontend que você mesmo desenvolva.
Instalar o pacote
Instale o plugin Conversor mais recente e estável:
dotnet add package Doconut.NET8.ConverterPara fixar o plugin na versão atual 26.7.0, passe a versão separadamente:
dotnet add package Doconut.NET8.Converter --version 26.7.0Mantenha o pacote Conversor na mesma versão que Doconut.NET8. O ID do pacote é
Doconut.NET8.Converter; .26.7.0 aparece apenas no nome do arquivo .nupkg baixado.
Registrar o plugin
Não existe um método AddConverter() — o modelo de plugins do Doconut é uniforme. Cada plugin, incluindo o Conversor, registra‑se da mesma forma: chame AddPlugin<TPlugin>() dentro de AddDoconut(). ConverterPlugin é distribuído em seu próprio pacote NuGet, Doconut.NET8.Converter, instalado ao lado do pacote base do visualizador.
builder.Services.AddDoconut(options =>
{
options.LicensePath = "Doconut.Viewer.lic";
options.AddPlugin<Doconut.Plugins.Converter.ConverterPlugin>();
});Esta chamada gera uma exceção na inicialização por falta de licença, um arquivo legado
TRIAL, ou uma licença não temporária que não concede a capacidadeConverter— umInvalidOperationExceptionlevantado de dentro deAddDoconut(), antes que o aplicativo atenda solicitações. Registros temporários de Demonstração/NFR são aceitos; após sua expiração de calendário, a conversão continua disponível com saída com marca d'água. Não há nível gratuito silencioso. Veja Configuração de Licença para saber como as licenças são carregadas.
Converter a partir de C#
Cada conversão retorna um MemoryStream buscável posicionado em 0, pronto para leitura ou cópia imediata. Resolva DocumentConverter a partir do DI onde precisar — ele é sem estado por design, portanto uma única instância pode ser reutilizada com segurança entre solicitações.
// Injete DocumentConverter; seu construtor é interno, então nunca `new` ele.
Stream pdf = await converter.ConvertAsync("contract.docx", ConversionTarget.Pdf, ct: ct);// sourceExtension inclui o ponto inicial. password é null a menos que o documento esteja 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);Dois detalhes que são fáceis de errar: sourceExtension na sobrecarga de stream deve incluir o ponto inicial (".xlsx", não "xlsx") — o conversor o compara com o catálogo de formatos e uma extensão sem ponto não será resolvida. E apesar do nome, WordToHtmlAsync retorna Task<Stream>, não Task<string> — você obtém o documento HTML (imagens incorporadas como Base64) como um stream, da mesma forma que todo outro resultado de conversão.
Formatos de destino
Pdf, Docx, Doc, Html, Xlsx, Pptx, Png, Jpeg, Csv, Tiff, Bmp, Gif, Svg, Xml,
Txt, Xls, Jp2, Rtf, Odt, Ods, Odp, Epub, Xps, WebpNem toda origem converte para todo destino — o plugin mapeia cada família de formato de origem (Word, Excel, PowerPoint, PDF, CAD, Imagem, Email, Diagrama, Projeto/Tarefa, PSD, documento web) para seu próprio conjunto fixo de destinos permitidos. Não codifique esse enum como a lista de destinos da sua UI: ?convert=open retorna o allowedTargets real para qualquer arquivo que acabou de ser enviado, e é isso que deve alimentar o seletor.
Widget incorporável
Os endpoints ?convert=open|run|download do widget são opcionais e desativados por padrão — seguros por padrão. Ative-os no servidor, juntamente com o registro do 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>Sem AddConverterWidget(), os três endpoints ?convert= respondem com 404 — mas o próprio arquivo JS ainda é servido de qualquer forma (é um recurso estático simples incorporado; apenas os endpoints com os quais ele se comunica são restritos). AddConverterWidget() ainda requer que o plugin Converter esteja registrado e uma licença que conceda Converter — isso não concede direitos de conversão por si só.
Personalize o widget
Opções de inicialização passadas para Doconut.convert(selector, options):
| Opção | Tipo | Padrão | Observações |
|---|---|---|---|
basePath | string | /doconut | Caminho base para os endpoints ?convert=; deve corresponder ao ramo ASP.NET onde UseDoconut() está realmente montado (normalmente coordenado através de MiddlewarePath) |
resPath | string | /doconut-res | Aceito para consistência de configuração com outros widgets Doconut; o widget conversor atualmente não gera nenhuma URL a partir dele |
maxUploadMb | number | 25 | Apenas verificação prévia no cliente — rejeita um arquivo excessivamente grande antes do upload. O servidor impõe seu próprio limite de forma independente e responde com 413 se for excedido |
licenseUrl | string | null | null | Quando definido, transforma o aviso de marca d'água na tela de resultado em um link para esta URL |
labels | object | {} | Substitui qualquer subconjunto das strings padrão em inglês do widget (texto de arrastar, botões, anúncios aria-live, mensagens de erro) |
Callbacks:
| Callback | Dispara quando | Carga |
|---|---|---|
onReady() | O widget renderizou sua tela ociosa/de arrastar | — |
onSourceLoaded({ token, pages, sourceExt, allowedTargets }) | ?convert=open tem sucesso | token de sessão da fonte, contagem de páginas, extensão da fonte (sem ponto inicial), lista de destinos permitidos |
onConverted({ downloadToken, resultToken, resultPages, downloadName, watermarked, target }) | ?convert=run tem sucesso | mesmos campos da resposta de execução, mais o target que foi solicitado |
onDownload({ downloadName, downloadToken }) | O usuário clica no link Download | dispara junto ao download nativo do navegador — não intercepta nem substitui |
onError({ phase, message }) | Uma solicitação de abrir ou executar falha | phase é 'open' ou 'run'; message é o erro do servidor sanitizado (ou uma mensagem do cliente para a verificação prévia de tamanho de upload) |
Doconut.convert() retorna a própria instância do widget — mantenha-a para controlar o widget programaticamente:
const conv = Doconut.convert('#doconut-convert', { basePath: '/doconut' });
conv.reset(); // volta para a tela idle/drop; não dispara onReady novamente
conv.loadFile(file); // inicia o fluxo com um objeto File; não faz nada a menos que esteja ocioso
conv.destroy(); // remove ouvintes, esvazia o mount; a instância torna‑se inutilizável após issoConstrua sua própria interface
O widget é apenas um cliente para este contrato HTTP — construa sua própria interface diretamente contra ele para uma experiência de usuário diferente. Todas as três rotas ficam sob o ramo ASP.NET onde UseDoconut() está montado (normalmente /doconut):
| Rota | Objetivo | Resposta de sucesso |
|---|---|---|
POST ?convert=open (multipart, campo file) | Enviar e abrir um documento fonte para visualização | 200 — { token, pages, sourceExt, allowedTargets } |
POST ?token=<token>&convert=run&target=<ext> | Converter a fonte armazenada para target | 200 — { downloadToken, resultToken, resultPages, downloadName, watermarked } |
GET ?convert=download&token=<downloadToken> | Transmitir o arquivo convertido | 200 — bytes do arquivo, Content-Disposition: attachment, Cache-Control: no-store |
Os bytes da fonte enviada são armazenados no servidor com um TTL de 30 minutos; quando esse período expira, run responde com 404 e o arquivo deve ser reaberto. O resultado convertido permanece na mesma área de armazenamento — downloadToken obtém sua própria janela fresca de 30 minutos quando a conversão termina — enquanto resultToken é um token de sessão de visualizador comum cujo tempo de vida segue o cache de sessão do visualizador, independente da área de armazenamento.
sourceExt na resposta open não tem ponto inicial (ex.: "docx") — a convenção oposta ao parâmetro sourceExtension em DocumentConverter.ConvertAsync, que requer um.
Modos de falha, agrupados por rota:
| Rota | Status | Quando | Corpo |
|---|---|---|---|
| qualquer | 404 | O widget não está habilitado (AddConverterWidget() nunca foi chamado) — verificado antes de qualquer das três rotas ser despachada | apenas status |
| qualquer | 405 | Verbo HTTP errado (open/run requer POST; download requer GET) | apenas status |
open | 413 | Arquivo enviado excede MaxUploadMb | { "error": "File is too large." } |
open | 400 | Sem corpo multipart, sem arquivo, ou extensão da fonte que não pode ser convertida | { "error": "..." } |
run | 400 | Token malformado (não é um GUID), ou um target que não pode ser analisado para um ConversionTarget | { "error": "Invalid token." } / { "error": "Unknown target format." } |
run | 400 | target não está no allowedTargets da fonte | { "error": "That target format is not available for this file." } |
run | 404 | O upload armazenado expirou (TTL de 30 minutos) ou o token nunca foi aberto | { "error": "Upload expired — please re-open the file." } |
open, run | 500 | Processamento falhou internamente | { "error": "<sanitized message>" } — sanitizado da mesma forma que todo outro caminho de erro Doconut; nunca vaza nomes internos do motor |
download | 400 | Token malformado (não é um GUID) | apenas status |
download | 404 | Token de download desconhecido ou expirado | apenas status |
Propriedade de recurso
O conversor retorna um MemoryStream buscável posicionado em zero. O chamador possui esse fluxo e deve descartá‑lo após copiar ou retornar seu conteúdo. O serviço DocumentConverter em si é sem estado e é resolvido por injeção de dependência; não construa nem descarte o serviço manualmente.
Para o widget web, os armazenamentos de upload e download têm TTLs independentes de 30 minutos. Um resultToken de visualizador segue a duração da sessão do visualizador. Fechar um resultado de visualizador não exclui um armazenamento de download ainda válido, e redefinir o widget do navegador não estende nenhum dos TTLs.
Solução de problemas
| Sintoma | Verificação |
|---|---|
Falha ao resolver DocumentConverter | O registro de ConverterPlugin ocorreu dentro de AddDoconut() |
| Aplicação falha durante a inicialização | A licença carregada concede Converter |
| Conversão de fluxo indica que o formato não é suportado | sourceExtension inclui o ponto inicial |
| JavaScript do widget carrega, mas as solicitações retornam 404 | AddConverterWidget() não foi chamado |
| Solicitações do widget usam a URL errada | basePath corresponde ao branch onde UseDoconut() está mapeado |
| Alvo está ausente | Use allowedTargets retornado por convert=open; nem toda fonte suporta cada alvo de enum |
| Download expirado | Repita convert=open/convert=run; os tokens de armazenamento são intencionalmente temporários |
Marca d'água
Com ConverterPlugin registrado, a licença do host está em um dos três estados:
| Estado da licença | Portão de inicialização | Saída da conversão |
|---|---|---|
Licença de visualizador paga concedendo Converter, dentro do seu período de validade | Passa | Limpa — watermarked: false |
| Licença de avaliação ativa (demo/NFR) | Passa | Converte com sucesso, marcado com a marca d'água de avaliação — watermarked: true |
Sem licença, um arquivo legado TRIAL, ou uma licença não temporária que não concede Converter | Aplicativo nunca inicia — o portão de inicialização descrito acima lança | — |
| Licença temporária/demo expirada | Registro sobrevive à expiração | Converte com a marca d'água de avaliação — watermarked: true |
Ambos os caminhos de chamada calculam o indicador a partir da mesma regra: a fachada C# DocumentConverter o deriva internamente do IsViewerLicensed e do estado IsTemporary da licença, e o manipulador ?convert=run do widget realiza a verificação equivalente (IsViewerLicensed && !IsTrial && !IsTemporary) para preencher o campo watermarked que ele devolve. Uma integração pode ser construída e testada de ponta a ponta em uma licença de avaliação antes da compra — apenas os bytes de saída mudam.
Esta página foi útil?