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
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í:
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:
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.