Como o Viewer Funciona
O ciclo de vida da solicitação de documento
Doconut renderiza documentos como imagens paginadas servidas através de middleware ASP.NET Core. Entender o ciclo de vida — abrir, token, solicitações de página, fechar — explica quase todo comportamento que você observará, incluindo as mensagens de erro.
As três partes móveis
Viewer— o serviço público que você injeta. Ele abre documentos e devolve tokens de sessão.- A sessão do documento — um objeto do lado do servidor que mantém o documento carregado, indexado por um token em
IMemoryCache. - O middleware Doconut — adicionado por
UseDoconut(); responde a todas as solicitações que o widget do navegador faz (pages,thumbnails,search,annotations, …), sempre autenticado pelo token.
Viewer é sem estado — por design
Viewer é selado, não mantém estado de documento por solicitação e deliberadamente não implementa IDisposable. As sessões vivem independentemente no gerenciador de sessões e são limpas por expiração do cache ou por um CloseDocument(token) explícito.
Você não o constrói mais. AddDoconut() o registra como um serviço transitório; injete-o onde precisar:
app.MapPost("/api/open", async (string fileName, Viewer viewer) =>
{
var token = await viewer.OpenDocumentAsync($"files/{fileName}");
return Results.Content(token, "text/plain");
});Em uma aplicação MVC, receba-o como parâmetro do construtor; em uma view Razor, use @inject Doconut.Viewer Viewer. Caches de instâncias de Viewer de propriedade da aplicação não são mais necessárias — e não são corretas, pois não mantêm nada que valha a pena cachear.
O que acontece dentro de OpenDocumentAsync
- Portão de licença. Uma licença rejeitada ou expirada por versão (na lista negra, adulterada ou uma compilação fora da janela de atualização da licença) lança imediatamente uma
LicenseException, com o motivo da rejeição como mensagem — a abertura nunca degrada silenciosamente para uma licença inválida (em contraste com ausente). Uma licença Temporária ou de assinatura expirado por calendário é a exceção: não lança — degrada para uma marca d'água. - Criação da sessão. A fábrica do visualizador escolhe o visualizador de formato correto para a extensão do arquivo e carrega o documento (veja o Pipeline de Renderização). A sessão é armazenada em
IMemoryCachesob um novo token GUID com expiração deslizante —DocOptions.TimeOutminutos, padrão 60. Cada solicitação de página reinicia o relógio. - Registro de segurança. Com
UnsafeMode = false(o padrão), o token é vinculado à sessão ASP.NET do chamador: um marcadorsecure-{token}é gravado na sessão, de modo que somente a sessão do navegador que abriu o documento pode solicitar suas páginas. - O token é devolvido. Ele é a única credencial para tudo que se segue.
Não há uma etapa de pré-aquecimento separada. A biblioteca anterior expunha InitCache() para esse propósito; ela não existe mais, e nada a substitui.
As três sobrecargas diferem apenas na entrada: um caminho de arquivo, um caminho de arquivo mais uma configuração por formato (PdfConfig, WordConfig, …), ou um Stream mais um FileInfo cuja extensão determina a detecção de formato.
Como o widget obtém páginas
O widget cliente chama o middleware Doconut com o token na string de consulta. O que o middleware faz depende da solicitação:
| Consulta | Propósito |
|---|---|
?token=…&page=N | Imagem da página renderizada (PNG) |
?token=…&page=N&thumb=1 | Miniatura |
?token=…&zoom=… | Renderização da página com zoom |
?token=…&search=term | Busca de texto completo (restrita por licença) |
?token=…&bookmarks | Estrutura do documento/marcadores |
?token=…© / &showlinks / &fileFormat | Cópia de texto, hyperlinks e informações de formato |
?token=…&meta | Metadados técnicos DICOM; retorna 501 para uma sessão DICOM neste pacote |
?token=…&action=rotate/flip/close | Ações de página e fechamento explícito |
?token=…&AnnSave=… / &AnnLoad | Salvar/carregar anotações |
Cada um desses caminhos valida primeiro:
- Sem token → o middleware retorna 404 (ou um banner de versão quando
ShowDoconutInfo = true). - Token desconhecido ou expirado → uma imagem de erro com
Document session not found. Please re-open document. - Middleware de sessão ausente (com
UnsafeMode = false) → HTTP 500 comSession middleware not configured. Call UseSession() before UseDoconut(). - Token aberto por uma sessão de navegador diferente → uma imagem de erro com
You Are Not Authorized To View This Page.
Onde o middleware é montado
UseDoconut() responde a solicitações que carregam um token, onde quer que você o monte. A aplicação de referência mantém o formato histórico de solicitação DocImage.axd em um ramo MapWhen, de modo que um cliente existente continua chamando a URL que sempre usou. Seja qual for a sua escolha, o BasePath do cliente deve concordar com ele — veja ConfiguraçãoDoVisualizador.
Servir páginas a partir de armazenamento compartilhado em vez do nó de abertura é um arranjo totalmente diferente; veja Implantações Distribuídas.
Fechando um documento
viewer.CloseDocument(token);CloseDocument remove a sessão do cache (que descarta o motor de documento subjacente e libera sua memória imediatamente), exclui o marcador secure-{token} e revoga a concessão de acesso. Chamá‑lo é opcional — a expiração deslizante faz a mesma limpeza automaticamente — mas para documentos grandes é a forma educada de liberar memória assim que o usuário termina.
Ele é chamado no Viewer injetado. O padrão anterior — construir um Viewer de curta duração em um bloco using apenas para fechar um token — não tem equivalente e não é necessário.
Conclusões
- Um documento aberto = uma sessão = um token. Tokens são por sessão de navegador, não URLs globais.
- O token expira em uma janela deslizante; um visualizador deixado ocioso além de
DocOptions.TimeOutprecisa ser reaberto. Viewerpode ser injetado e compartilhado livremente; as sessões carregam todo o estado.
Esta página foi útil?