[Ajuda] Renderizar PDF a partir de HTML com Node.js

Situação: tenho alguns templates em html + css e estava usando Puppeteer. Localmente estava dando certo, porém rodo minha api na AWS, ao upar a api com o puppeteer, dá erro, e configurar o chromium/lambda no estado atual não é possível para mim.

Estou tentando utilizar o html-pdf e html-pdf-node, porém está quebrando as imagens e até divs, fica cortado pela metade nas páginas. O css parece não funcionar muito bem com essa lib, os exemplos utilizam até bootstrap, achei que ajudaria, mas em partes apenas.

Alguém teria alguma outra sugestão ou dica ?

const pdf = require("html-pdf-node");
const generatePDF = async (htmlContent, format, landscape) => {
  const options = {
    format, // Tamanho do papel, como "A4" ou "Letter"
    landscape, // Orientação: true para paisagem, false para retrato
    preferCSSPageSize: true,
    printBackground: true,
  };

  // Criação do PDF a partir do HTML
  const file = { content: htmlContent };
  try {
    const pdfBuffer = await pdf.generatePdf(file, options);
    return pdfBuffer;
  } catch (error) {
    throw new Error(`Erro ao gerar PDF: ${error.message}`);
  }
};

Utilizo esse código, que diz que resolve a quebra, porém sem sucesso 100%

 /* Evita quebras de elementos dentro de uma página */
      .no-break,
      .header,
      .checklist-item,
      .value-item {
        page-break-inside: avoid;
        break-inside: avoid;
      }

Gera o pdf no front e chama o visualizador de pdf do navegador. depois o usuário se vira pra baixar ou imprimir.

Por enquanto vou fazer o que o colega Pedroaf0 falou... Tenho uma parte admin onde posso gerar o relatório e faço esse window.print; Mas não é o ideal como o welovetech disse. Um diferencial do sistema vai ser essa geração de relatório a partir do aplicativo mobile. Mas como não escalei ainda, é bem viável

Tente usar o Gotenberg. Encontrei recentemente e estou usando em todos os meus projetos. Ele oferece várias maneiras de criar PDFs

Ele faz exatamente o que o pupeeeter faz, mas usando o libre office. Mais leve e eficiente.

Tenho um usecase parecido com o seu em minha aplicação B2B, onde usuarios podem construir seus PDFs. Inicialmente parti para uma abordagem construindo esse PDF no frontend, e usando diversas ferramentas que o convertiam para que o usuário pudesse fazer o download.

Decidimos tentar essa abordagem fazendo uma POC, e logo vimos as infinitas limitações que esse tipo de solução teria.

Construimos então toda a lógica no backend, o que se mostrou um completo sucesso. Utilizamos a lib pdfkit. Acho que não há melhor do que ela hoje. Eu não recomendo tentar transformar HTML diretamente em um PDF, isso vai levar a diversas inconsistencias visuais, quebra de linhas incorretas, overlap de conteudos, quebra de paginas incorretas e etc, o que aconteceu conosco em nossas diversas POCs dessa feature.

Com o pdfkitconseguimos criar todo tipo de PDF personalizado. Recomendo dar uma olhada: https://pdfkit.org/

Como comentou que vai rodar em lambdas, recomendo tomar cuidado ao lidar com muitas imagens bufferizadas nas paginas, isso geralmente acarreta em um uso excessivo de memória. Sucesso no projeto.

Então estou utilizando em partes esse PDFkit, mas o puppeteer por exemplo renderiza o html/css bem bonito e sem quebras, melhor solução até agora, tirando o Pdfkit. O PDFkit é realmente bom, vou falar que seria por desinteresse ou falta de conhecimento técnico meu, me irritei fazendo os templates kkkkkkkkk Apesar de tudo, estou utilizando o Pdfkit também. Muito obrigado Jorge!

Uma coisa que pensei é verificar com o windom.print se a página html + css está sendo a mesma dessa lib que utilizado com nodejs. Se for, pode ser que resolva com algumas linhas de css.

Se não der certo. veja na biblioteca issues abertas/fechadas no repositório. veja se já tiveram esse problema.

Use --no-sandbox dentro de args ao instanciar seu Browser. Veja sobre outras configurações de Sandbox como --disable-setuid-sandbox, pois elas interagem diretamente com as configurações de superusuário do Chrome.

Se eu colocar essas options do -no-sandbox, ele pode rodar na aws sem problemas ?
Boa tarde! Vc pode utilizar a configuração `headless = true` para remover a janela do browser que funciona com servidores sem interface gráfica. Segue a função para gerar qualquer pdf que utilizo com o pupperteer ```js async function generatePDF(url,puppeteerConf={}) { if(browser==false) browser = await puppeteer.launch({ headless: true, ignoreHTTPSErrors: true }); // Puppeteer can only generate pdf in headless mode. const pdfConfig = Object.assign({ format:'A4', landscape:true, printBackground:true }, puppeteerConf); var returnedPdf = null; const page = await browser.newPage().catch(err => { if(browser) browser.close(); browser=false; throw 'newPage crash:'+err; }); return new Promise( (resolve, reject) => { page.on('error', (err) => { try { page.close(); } catch(e) { }; reject('page crash:'+err); }); page.goto(url, {waitUntil: 'networkidle0', timeout: 25000} ) .then( () => { if(typeof page['emulateMediaType']=='function') page.emulateMediaType('screen'); else page.emulateMedia('screen'); }) .then( () => page.pdf(pdfConfig) ) .then( pdf => { returnedPdf = pdf }) .then( () => page.close() ) .then( () => { resolve(returnedPdf); }) .catch(err => { reject(err); }); }); } ```

Voce pode também utilizar o Libre Office ao invés do pupeeeter. É mais eficiente, e voce pode usar chields para executar os comandos. Só nao sei se ele consegue abrir o HTML, teria que testar

Uso o weasyprint para gerar pdf em relatórios na empresa. https://weasyprint.org/

Até hoje a melhor opção para mim foi o wkhtmltopdf.