Principais pontos
- Defina o formato pdf em /html/convert; os outros formatos geram capturas de tela.
- Controle quando o instantâneo é capturado com wait_until e, somente quando necessário, com delay.
- Use autenticação de curta duração com escopo restrito ao documento; cabeçalhos e campos continuam visíveis no Assembly Status, então proteja o Assembly ID e a URL de status.
A maioria dos requisitos de PDF começa como uma página que já é renderizada corretamente em um navegador. Renderizar essa página no servidor costuma sair mais barato do que manter um segundo layout em uma biblioteca de PDF, desde que o momento da captura e as entradas sejam controlados.
O que mais importa
- Renderize a partir de uma URL de modelo estável e versionada, para que uma mudança de design não altere um documento já emitido.
- Mescle documentos com várias partes usando /document/merge em vez de concatenar PDFs por conta própria.
Renderize a página que você já tem
A maioria dos requisitos de PDF começa como uma página que já é renderizada corretamente em um navegador: uma fatura, um extrato, um relatório. Manter um segundo layout em uma biblioteca de PDF duplica esse trabalho e garante que os dois vão divergir. O Robot /html/convert renderiza a página com um navegador headless e retorna o resultado, e é a definição de format: "pdf" que distingue um documento de uma captura de tela. O mesmo Robot produz jpeg, jpg e png, que são imagens da página, e não documentos paginados.
O Robot aceita tanto uma url para renderizar quanto um arquivo HTML enviado por upload. Renderizar uma URL costuma ser a melhor escolha para documentos que já existem como páginas, porque mantém uma única fonte da verdade. Enviar HTML por upload é mais adequado para documentos montados na hora, quando não existe uma URL estável.
{
"steps": {
"rendered": {
"robot": "/html/convert",
"url": "https://example.com/inv/1043?v=3",
"format": "pdf",
"wait_until": "networkidle"
},
"exported": {
"use": "rendered",
"robot": "/s3/store",
"credentials": "my_s3_credentials",
"acl": "bucket-default",
"path": "inv/1043/${assembly.id}.pdf"
}
}
}format: "pdf"
Produz o documento. Os outros formatos capturam uma imagem da página.
url ou upload
Renderize uma página existente pela URL ou envie por upload o HTML gerado quando não houver uma URL estável.
omit_background
Aplica-se apenas à saída de imagem. A transparência não pode ser levada para um PDF.
Controle quando o instantâneo é capturado
Um documento pode chegar meio vazio quando um gráfico ou uma fonte não está pronto no momento da captura. wait_until seleciona um estado de carregamento do navegador e tem como padrão networkidle; seus outros valores são domcontentloaded, load e commit. A ociosidade da rede não prova que os dados da aplicação, uma animação ou um gráfico atrasado terminaram de renderizar. Selecionar um estado anterior pode encurtar a espera, mas não corrige o conteúdo que continua ausente com o valor padrão.
delay adiciona uma pausa fixa depois do estado de carregamento selecionado. Para conteúdo renderizado tardiamente, primeiro faça a página renderizar a partir de dados prontos, quando possível, e depois teste um atraso limitado quando a página não puder expor sua prontidão pelo comportamento de carregamento. Essa pausa aumenta a latência em cada renderização, inclusive nas que não precisavam dela. Verifique o PDF real em vez de tratar a ociosidade da rede ou uma espera fixa como garantia de que o conteúdo está completo.
wait_until
O padrão é networkidle. Um estado de carregamento do navegador não garante que o conteúdo da aplicação esteja pronto.
delay
Adiciona uma pausa fixa em cada renderização depois do estado de carregamento selecionado. Teste-a para conteúdo que termina mais tarde.
Folha de estilo de impressão
Verifique a página na visualização de impressão do navegador antes de renderizá-la no lado do servidor.
Acesse páginas protegidas sem vazar credenciais
Como a renderização executa um navegador real, a página precisa estar acessível a partir da Transloadit. Os documentos geralmente ficam protegidos por autenticação, o que deixa duas opções viáveis. O parâmetro headers envia a autenticação junto com a requisição, o que é adequado para acesso baseado em token. Como alternativa, emita uma URL assinada de curta duração que conceda acesso a exatamente um documento por um curto período.
Use um único token de curta duração, preferencialmente de uso único, com escopo restrito a um documento. Qualquer pessoa que tenha o Assembly ID ou a URL de status pode recuperar o Assembly Status sem nova autenticação, inclusive seus campos. O exemplo passa o token por fields.token, então ele fica visível ali. notification_payload: ["without_params"] remove params, template e merged_params das notificações; não remove os campos nem oculta dados do Status. Nunca use aqui um token reutilizável da conta. Mantenha IDs, URLs de status e respostas brutas de status fora de logs públicos e de respostas ao cliente, oculte tokens nos logs da aplicação e faça o acesso ao documento expirar independentemente da retenção do Status.
{
"notification_payload": ["without_params"],
"steps": {
"rendered": {
"robot": "/html/convert",
"url": "https://example.com/reports/q3",
"format": "pdf",
"wait_until": "networkidle",
"headers": {
"Authorization": "Bearer ${fields.token}"
}
}
}
}headers
Transporta fora da URL um token de curta duração com escopo de documento. Trate os parâmetros e os logs da Assembly como sensíveis.
URLs assinadas não reutilizáveis
Conceda acesso a um único documento por um curto período quando a autenticação por cabeçalho não estiver disponível.
Nunca na string de consulta
Credenciais colocadas ali ficam registradas em todo lugar onde a URL renderizada é armazenada.
Faça um documento reemitido ficar idêntico ao original
Uma fatura é um registro usado para fins legais, e a versão que um cliente recebe em março ainda deve ser renderizada de forma idêntica em novembro. Dois hábitos garantem isso. Renderize a partir de uma URL de modelo versionada, para que uma mudança posterior de design não possa alterar um documento já emitido, e armazene o arquivo resultante em vez de gerá-lo novamente sob demanda.
Vale a pena tratar explicitamente documentos montados a partir de várias partes. Use /document/merge com document_1, document_2 e os aliases as seguintes para definir a ordem, e bundle_steps: true para reunir as partes. Isso evita depender dos nomes dos arquivos de entrada ou dar a um segundo serviço acesso às partes.
{
"steps": {
"cover": {
"robot": "/html/convert",
"url": "https://example.com/stmt/cover?v=3",
"format": "pdf",
"wait_until": "networkidle"
},
"detail": {
"robot": "/html/convert",
"url": "https://example.com/stmt/detail?v=3",
"format": "pdf",
"wait_until": "networkidle"
},
"statement": {
"use": {
"steps": [
{ "name": "cover", "as": "document_1" },
{ "name": "detail", "as": "document_2" }
],
"bundle_steps": true
},
"robot": "/document/merge"
}
}
}Versione o modelo
Uma mudança de design deve gerar novos documentos, e não alterar retroativamente os que já foram emitidos.
Armazene, não gere de novo
Mantenha o arquivo gerado para que uma reemissão seja uma cópia, e não uma nova renderização.
/document/merge
Combina documentos de várias partes em uma única Assembly; use aliases as explícitos para controlar a ordem.
Mantenha previsível o custo de renderização
A renderização de uma página é mais cara do que uma conversão de formato, porque inicia um navegador, busca sub-recursos e espera a página se estabilizar. Esse custo é aceitável para um documento que um cliente solicitou, e um desperdício quando o mesmo extrato é renderizado de novo toda vez que alguém abre uma visualização em lista. A solução habitual é renderizar uma vez, no momento em que o documento se torna definitivo, e depois servir o arquivo armazenado.
A geração em massa merece um tratamento à parte. Uma execução de fim de mês que produz milhares de extratos não deve concorrer com a renderização pela qual um cliente está esperando, e um delay fixo aplicado a um lote desses se multiplica em tempo e dinheiro reais. Medir o custo por documento emitido, em vez de por Assembly, costuma revelar esses padrões rapidamente.
Renderize na finalização
Gere o arquivo quando o documento se tornar definitivo, não a cada visualização.
Separe as execuções em massa
Mantenha os lotes de fim de mês longe das renderizações pelas quais uma pessoa está esperando.
Audite atrasos fixos
Uma pausa de um segundo passa despercebida uma vez, mas sai cara ao longo de dez mil documentos.
Verifique o documento antes que um cliente o veja
Uma renderização pode ser bem-sucedida e ainda assim estar errada. O Robot retorna um PDF válido independentemente de o gráfico ter sido desenhado ou não, então uma verificação que só pergunta se um arquivo foi produzido não vai detectar uma página em branco. Asserções simples detectam a maior parte dos problemas: um tamanho em bytes plausível, uma contagem de páginas esperada e a presença de uma string conhecida, como o número do documento.
Renderizar para png junto com o PDF durante o desenvolvimento oferece uma verificação visual rápida, fácil de conferir a olho na revisão, e comparar uma renderização nova com uma imagem de referência armazenada detecta regressões de layout que uma verificação de tamanho em bytes não consegue detectar. Nenhuma dessas verificações pertence ao caminho de produção, mas vale a pena manter ambas no pipeline que publica alterações de modelo.
Faça asserções sobre o conteúdo, não sobre a existência
Verifique a contagem de páginas e um identificador conhecido, em vez de apenas verificar se um arquivo existe.
Renderizações em imagem para revisão
Um png da mesma página permite revisar alterações de modelo com uma olhada rápida.
Compare com uma referência
A comparação visual detecta regressões de layout que as verificações de tamanho deixam passar.
Detalhes técnicos que vale a pena conhecer
- O parâmetro format aceita jpeg, jpg, pdf e png. Apenas pdf produz um documento; os demais capturam uma imagem da página.
- O parâmetro omit_background se aplica à saída em imagem e não tem efeito quando format é pdf, portanto a transparência não pode ser levada para o documento.
- O parâmetro wait_until tem como padrão networkidle e seleciona um estado de carregamento do navegador. Ele não garante que gráficos, fontes ou dados da aplicação atrasados estejam prontos.
- O parâmetro delay adiciona uma pausa fixa depois que o estado de carregamento é atingido. Teste um atraso limitado para conteúdo renderizado tardiamente e considere a latência adicional em cada renderização.
- Uma fatura renderizada é um registro usado para fins legais. Renderizar a partir de uma URL de modelo imutável e armazenar o arquivo resultante, em vez de gerá-lo novamente sob demanda, mantém uma cópia reemitida idêntica à original.
- Como a renderização executa um navegador real, a página precisa estar acessível a partir da Transloadit. Páginas protegidas por um cookie de sessão precisam de uma URL assinada de uso único ou das credenciais passadas pelo parâmetro headers.
Uma abordagem prática
- 1
Crie o documento como uma página normal com uma folha de estilo de impressão e verifique-o primeiro em um navegador.
- 2
Renderize-o com /html/convert usando o formato pdf e um wait_until explícito.
- 3
Armazene o resultado em um bucket privado junto com os identificadores que o produziram. Use bucket-default para buckets S3 com ACLs desativadas e aplique o controle de acesso pela política do bucket.
- 4
Mescle as páginas complementares em um único arquivo com /document/merge quando o documento tiver várias partes.
Quando a Transloadit é útil
Use /html/convert com o formato pdf quando o documento já existir como página web ou puder ser renderizado como uma. Aponte-o para uma url ou faça upload de HTML e deixe o Robot renderizar o arquivo enviado. Combine-o com /document/merge quando várias páginas precisarem ficar em um único arquivo.
Limite da arquitetura
/html/convert renderiza uma página com um navegador headless, então produz uma cópia visual paginada, e não um PDF acessível e com tags. Documentos que precisam de estrutura selecionável, campos de formulário ou formatos de arquivamento de longo prazo, como PDF/A, devem ser produzidos por um gerador de documentos dedicado.
Perguntas frequentes
Por que meu PDF está sem gráficos ou fontes?
A página pode não ter terminado de renderizar o conteúdo da aplicação. O valor padrão de wait_until já é networkidle, que não garante que gráficos ou fontes atrasados estejam prontos. Sempre que possível, renderize a partir de dados prontos ou teste um atraso limitado depois do estado de carregamento. Inspecione o PDF para confirmar que o conteúdo ausente aparece; a pausa fixa aumenta a latência em cada renderização.
Posso gerar um PDF com fundo transparente?
Não. omit_background afeta a saída de imagem e não tem efeito quando format é pdf. Se a transparência for necessária, renderize em png no lugar disso e insira essa imagem em um documento.
Como renderizo uma página que exige login?
Passe a autenticação pelo parâmetro headers ou emita uma URL assinada de curta duração, restrita a esse único documento. Evite colocar credenciais na string de consulta, porque a URL renderizada fica registrada em todos os logs que registram a renderização.
A saída é um PDF acessível e com tags?
Não. Um navegador headless produz uma cópia visual paginada, e não um documento com tags que tenha ordem de leitura, campos de formulário ou conformidade com PDF/A. Requisitos desse tipo exigem um gerador de documentos dedicado, e não a renderização de uma página.
Como combino várias páginas renderizadas em um único arquivo?
Renderize cada parte e passe os resultados para /document/merge na mesma Assembly. Atribua os aliases document_1, document_2 e os demais aliases as e ative bundle_steps: true. Sem aliases explícitos, o Robot ordena pelo nome do arquivo, e não pela ordem dos nomes dos Steps no array.