Node.JS

Crear PDF con Node.js

En este post de programación con JavaScript del lado del servidor te mostraré cómo crear un PDF usando Node.js y el paquete html-pdf.

Gracias a esto vamos a generar un PDF usando una plantilla HTML. Aunque al inicio puede parecer complejo verás que en realidad es una forma muy simple de crear facturas, tickets y todo tipo de documentos PDF.

Además de guardar el PDF en el almacenamiento, te enseñaré cómo mostrar el PDF directamente en el navegador usando Express.

Instalando dependencias

Primero instala globalmente html-pdf así:

npm install -g html-pdf

Luego dentro de tu proyecto instala la dependencia igualmente:

npm install html-pdf

La plantilla HTML

Plantilla HTML para crear PDF con Node.js – renderizada en navegador

Quiero que quede claro que el resultado de la conversión no será el mismo que cuando vemos el HTML en un navegador web.

Mejor míralo de otro modo: es una forma fácil de crear un PDF en Node.js usando HTML, en lugar de diseñar el PDF usando coordenadas o cosas raras.

Así que no esperes que todas las cosas funcionen y se vean exactamente igual (sobre todo con los estilos). Dicho esto, tenemos la plantilla HTML:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Crear PDF con Node.js</title>
    <style>
        img {
            max-height: 250px;
        }
    </style>
</head>

<body>
    <h1>Creando PDF con Node.js</h1>
    <a href="https://parzibyte.me/blog">By Parzibyte</a>
    <p>Soy HTML que será convertido a un PDF</p>
    <p>El valor pasado por Node es: {{valor}}</p>
    <pre>
        <code>
            const saludo = "Hola mundo";
        </code>
    </pre>
    <p>También puedes usar imágenes de internet:</p>
    <img src="https://github.com/parzibyte.png" alt="Imagen de Parzibyte">
    <p>O imágenes locales:</p>
    <img src="file:///C:/Users/parzibyte/Documents/desarrollo/node/crear-pdf/abeja.jpg" alt="Imagen de una abeja">
</body>

</html>

Podemos cargar imágenes locales a través del protocolo file:/// pasando la ruta absoluta del archivo (si pruebas el ejemplo y no te funciona, revisa la ruta) así como cargar imágenes de cualquier lugar de internet.

Como puedes ver en la imagen del encabezado, la plantilla HTML funciona bien. Ya solo falta pasarle los datos desde Node.js y convertirlo a PDF.

Crear PDF y guardar en el almacenamiento

Para este primer ejemplo vamos a crear el PDF con JavaScript del lado del servidor y guardarlo en el disco duro. El código completo queda así:

/**
 * https://parzibyte.me/blog
 */const pdf = require("html-pdf");
const fs = require("fs");
const ubicacionPlantilla = require.resolve("./plantilla.html");
let contenidoHtml = fs.readFileSync(ubicacionPlantilla, 'utf8')
const valorPasadoPorNode = "Soy un valor pasado desde JavaScript";
contenidoHtml = contenidoHtml.replace("{{valor}}", valorPasadoPorNode);
pdf.create(contenidoHtml).toFile("salida.pdf", (error) => {
    if (error) {
        console.log("Error creando PDF: " + error)
    } else {
        console.log("PDF creado correctamente");
    }
});

Primero importamos a html-pdf así como fs. El módulo de fs (filesystem) nos permitirá leer el contenido del archivo HTML como cadena.

Después, en la línea 9, pasamos los valores. Básicamente es remplazar lo que haya entre llaves por el valor verdadero.

Finalmente en la línea 10 creamos el PDF pasándole la cadena HTML y pasamos el resultado a un archivo, indicando en primer lugar la salida y en segundo lugar un callback en donde estamos esperando un posible error.

Al ejecutarlo con: node guardar.js se genera un PDF llamado salida.pdf que se ve así:

PDF creado con JavaScript, Node.js y html-pdf

Si te fijas, se ve igual que cuando veíamos el HTML en el navegador. Además, ahora ya estamos pasando el valor. Puedes ver el PDF generado por si todavía te quedan dudas: Ejemplo de PDF creado con Node.js y JavaScript

Generar PDF con Express

El código que te mostré arriba puede ser colocado dentro de una aplicación web de express para guardar el PDF en el almacenamiento cuando un usuario haga una petición a tu sitio web o algo parecido.

Sin embargo puede darse el caso de que quieras generar un PDF con Node.js y mostrarlo directamente en el navegador. Para ello la cosa no cambia mucho. El código interesante es el siguiente:

app.get('/', (peticion, respuesta) => {
    // Podemos acceder a la petición HTTP
    const valorPasadoPorNode = "Soy un valor pasado desde JavaScript";
    contenidoHtml = contenidoHtml.replace("{{valor}}", valorPasadoPorNode);
    pdf.create(contenidoHtml).toStream((error, stream) => {
        if (error) {
            respuesta.end("Error creando PDF: " + error)
        } else {
            respuesta.setHeader("Content-Type", "application/pdf");
            stream.pipe(respuesta);
        }
    });
});

Como puedes ver ahora invocamos a toStream y en caso de que no haya error, pasamos el stream hacia la respuesta además de poner un encabezado para que el navegador (en caso de soportarlo) muestre el PDF o al menos entienda qué tipo de archivo le estamos enviando.

Si tú todavía no tienes una app de express pero igualmente quieres probar, el código completo de ejemplo es el siguiente:

/**
 * Tomado de https://parzibyte.me/blog/2019/05/27/node-js-express-ejemplo-creacion-proyecto/
 * By Parzibyte
 */// Importar dependencias
const express = require("express"),
    app = express(),
    pdf = require("html-pdf"),
    fs = require("fs");

// Constantes propias del programa
const ubicacionPlantilla = require.resolve("./plantilla.html"),
    puerto = 3000;
let contenidoHtml = fs.readFileSync(ubicacionPlantilla, 'utf8');
// Definir rutas
app.get('/', (peticion, respuesta) => {
    // Podemos acceder a la petición HTTP
    const valorPasadoPorNode = "Soy un valor pasado desde JavaScript";
    contenidoHtml = contenidoHtml.replace("{{valor}}", valorPasadoPorNode);
    pdf.create(contenidoHtml).toStream((error, stream) => {
        if (error) {
            respuesta.end("Error creando PDF: " + error)
        } else {
            respuesta.setHeader("Content-Type", "application/pdf");
            stream.pipe(respuesta);
        }
    });
});

// Una vez definidas nuestras rutas podemos iniciar el servidor
app.listen(puerto, err => {
    if (err) {
        // Aquí manejar el error
        console.error("Error escuchando: ", err);
        return;
    }
    // Si no se detuvo arriba con el return, entonces todo va bien ;)
    console.log(`Escuchando en el puerto :${puerto}`);
});

Recuerda instalar express y las dependencias listadas anteriormente. Después ejecuta el archivo, visita http://localhost:3000 y deberías ver el PDF:

Crear PDF con Node.js y mostrarlo en navegador con Express

Poniendo todo junto

Si quieres ver el código completo de ambos ejemplos puedes ver el repositorio de GitHub. Una vez lo tengas descargado abre una terminal en la carpeta del proyecto y ejecuta:

npm install

Una vez hecho eso, ya puedes probar ambos ejemplos ya sea con node guardar.js o node servir.js

Nota: no olvides que necesitas haber instalado Node previamente. Y si te gustan estas tecnologías por aquí te dejo más sobre JavaScript o Node.js.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Creador de credenciales web – Aplicación gratuita

Hoy te voy a presentar un creador de credenciales que acabo de programar y que…

1 semana hace

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

2 semanas hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

2 semanas hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

2 semanas hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

2 semanas hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

2 semanas hace

Esta web usa cookies.