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:

csharp
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

  1. 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.
  2. 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 IMemoryCache sob um novo token GUID com expiração deslizante — DocOptions.TimeOut minutos, padrão 60. Cada solicitação de página reinicia o relógio.
  3. Registro de segurança. Com UnsafeMode = false (o padrão), o token é vinculado à sessão ASP.NET do chamador: um marcador secure-{token} é gravado na sessão, de modo que somente a sessão do navegador que abriu o documento pode solicitar suas páginas.
  4. 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:

ConsultaPropósito
?token=…&page=NImagem da página renderizada (PNG)
?token=…&page=N&thumb=1Miniatura
?token=…&zoom=…Renderização da página com zoom
?token=…&search=termBusca de texto completo (restrita por licença)
?token=…&bookmarksEstrutura do documento/marcadores
?token=…&copy / &showlinks / &fileFormatCópia de texto, hyperlinks e informações de formato
?token=…&metaMetadados técnicos DICOM; retorna 501 para uma sessão DICOM neste pacote
?token=…&action=rotate/flip/closeAções de página e fechamento explícito
?token=…&AnnSave=… / &AnnLoadSalvar/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 com Session 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

csharp
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.TimeOut precisa ser reaberto.
  • Viewer pode ser injetado e compartilhado livremente; as sessões carregam todo o estado.

Esta página foi útil?