Generaci贸n de archivos PDF en Node.js con PDFKit

     

    Introducci贸n

    El formato PDF es uno de los formatos de documentos m谩s comunes para transferir informaci贸n. En aplicaciones web din谩micas, es posible que necesite exportar datos a un documento y PDF suele ser una opci贸n popular. En este art铆culo, discutiremos c贸mo generar archivos PDF en NodeJS usando el paquete NPM pdfkit.

    PDFKit es una biblioteca de generaci贸n de PDF de JavaScript para Node.js que proporciona una manera f谩cil de crear documentos PDF imprimibles de varias p谩ginas.

    Introducci贸n a PDFKit

    Creemos un directorio de proyecto, cd en 茅l e inicializar el proyecto Node con la configuraci贸n predeterminada:

    $ mkdir pdfkit-project
    $ cd pdfkit-project
    $ npm init -y
    

    Entonces vamos install pdfkit:

    $ npm install pdfkit
    

    Para usar el m贸dulo en el proyecto, lo importaremos a trav茅s de require():

    const PDFDocument = require('pdfkit');
    

    Crear un documento PDF usando PDFKit

    Para crear un documento PDF, necesitaremos importar el fs (sistema de archivos) m贸dulo tambi茅n. Canalizaremos el contenido de nuestro archivo PDF en un fsflujo de escritura para guardarlo. Echemos un vistazo a c贸mo hacer eso:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    let pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('SampleDocument.pdf'));
    pdfDoc.text("My Sample PDF Document");
    pdfDoc.end();
    

    Primero, importamos los m贸dulos requeridos, luego de lo cual, instanciamos el PDFDocument. Esta instancia es una secuencia legible. Estaremos canalizando esa secuencia a una secuencia de escritura para guardar el archivo.

    Si no est谩 familiarizado con el funcionamiento de las transmisiones, consulte nuestra Introducci贸n a las transmisiones de Node.js.

    Estamos usando el pipe() funci贸n para hacer esto y guardar el resultado SampleDocument.pdf en nuestro directorio ra铆z. Una vez creado, podemos agregarle contenido, a trav茅s del text funci贸n. Por supuesto que queremos end() la corriente al final.

    Cuando ejecutamos el c贸digo, un archivo PDF llamado SampleDocument.pdf se crea en la carpeta ra铆z de nuestro proyecto:

    $ node index.js
    

    Nota: Antes de intentar sobrescribir un archivo PDF existente, debe ser gratuito. Es decir, todas las Windows con ese archivo PDF deben cerrarse o el programa arrojar谩 un error.

    Formateo de texto en archivo PDF

    Por supuesto, pdfkit nos permite hacer mucho m谩s que agregar texto sin formato a un documento. Echemos un vistazo a algunas de las caracter铆sticas que ofrece.

    Colocaci贸n de texto

    Por defecto, el pdfkit El m贸dulo realiza un seguimiento de d贸nde se debe agregar el texto al documento, esencialmente imprime cada llamada al text() funci贸n en una nueva l铆nea.

    Puede cambiar d贸nde se imprime el texto dentro de la p谩gina actual, agregando las coordenadas xey de la ubicaci贸n donde desea que el texto se coloque como argumentos a la text() funci贸n.

    Por ejemplo:

    pdfDoc.text("Text positioned at (200,200)", 200, 200);
    

    Esto es 煤til porque le permite ajustar la posici贸n del texto, especialmente porque los documentos PDF tienen un aspecto universal independientemente de la m谩quina / sistema operativo en el que est茅n abiertos. Esto tambi茅n le permitir铆a, por ejemplo, imprimir texto sobre otro texto:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    var pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('SampleDocument.pdf'));
    
    pdfDoc.text("From Mon-Sat we will have a 10% discount on selected items!", 150, 150);
    pdfDoc
        .fillColor('red')
        .fontSize(17)
        .text("20%", 305, 150);
    
    pdfDoc.end();
    

    Ejecutar este c贸digo nos dar铆a:

    Ajuste y alineaci贸n de texto

    los pdfkit m贸dulo envuelve autom谩ticamente las l铆neas para que quepan entre los m谩rgenes, o en el width proporcionado (al escribir texto en columnas). En otras palabras, el lineBreak la opci贸n es true por defecto. Puedes cambiarlo a false al llamar al text() funci贸n:

    pdfDoc.text("very long text ".repeat(20), { lineBreak : false });
    

    Las nuevas p谩ginas tambi茅n se agregan autom谩ticamente seg煤n sea necesario, es decir, tan pronto como el contenido que desea agregar no encaja en la p谩gina actual en su totalidad. Sin embargo, tambi茅n puede pasar a la p谩gina siguiente antes de completar la anterior simplemente llamando a:

    pdfDoc.addPage();
    

    En cuanto a la alineaci贸n, pdfkit nos proporciona las opciones habituales – left (defecto), right, center y justify. Tenga en cuenta que establecer una alineaci贸n espec铆fica con lineBreak ajustado a false no funcionar谩, incluso si el texto cabe en una l铆nea.

    Tal como lineBreak, la align El par谩metro se establece pasando un objeto que contiene pares clave-valor al text() funci贸n. Veamos algunos ejemplos de alineaci贸n:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    var pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('text_alignment.pdf'));
    
    pdfDoc.text("This text is left aligned", { align: 'left'})
    pdfDoc.text("This text is at the center", { align: 'center'})
    pdfDoc.text("This text is right aligned", { align: 'right'})
    pdfDoc.text("This text needs to be slightly longer so that we can see that justification actually works as intended", { align: 'justify'})
    
    pdfDoc.end();
    

    Ejecutar el c贸digo anterior nos dar铆a un PDF con este aspecto:

    Estilo de texto

    los pdfkit El m贸dulo tambi茅n proporciona opciones que se pueden utilizar para aplicar estilo al texto en sus documentos PDF. Echaremos un vistazo a algunas de las opciones de estilo m谩s importantes, puede encontrar la lista completa de opciones en el Gu铆a PDF.

    Podemos pasar diferentes opciones como pares clave-valor al text() funci贸n, y tambi茅n encadenar varias otras funciones antes de llamar text() en absoluto.

    Una cosa muy importante a tener en cuenta es que las funciones encadenadas, como fillColor() (y despu茅s font(), fontSize(), etc.) afectar谩 a todo el texto despu茅s de esa llamada:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    var pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('text_styling.pdf'));
    
    pdfDoc
        .fillColor('blue')
        .text("This is a link", { link: 'https://pdfkit.org/docs/guide.pdf', underline: true });
    pdfDoc
        .fillColor('black')
        .text("This text is underlined", { underline: true });
    pdfDoc.text("This text is italicized", { oblique: true });
    pdfDoc.text("This text is striked-through", { strike: true });
    
    pdfDoc.end();
    

    La ejecuci贸n de este c贸digo generar谩 un archivo PDF con el siguiente contenido:

    Cambiar estilos en el medio de un p谩rrafo es un poco m谩s complicado, ya que encadenar m煤ltiples text() functions agrega una nueva l铆nea despu茅s de cada una de forma predeterminada. Podemos evitar esto configurando el lineBreak opci贸n de la primera text() llamar a false:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    var pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('text_styling2.pdf'));
    
    pdfDoc
        .fillColor('blue')
        .text("This text is blue and italicized", {oblique : true, lineBreak : false})
        .fillColor('red')
        .text(" This text is red");
    
    pdfDoc.end();
    

    Lo que nos dar铆a el resultado deseado:

    Crear listas

    Para agregar una lista de elementos en su documento PDF, el PDFDocument instancia tiene un list() funci贸n que toma una matriz de elementos de cadena (o matrices anidadas de cadenas) y las muestra como una lista de vi帽etas:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    let pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('lists.pdf'));
    
    let myArrayOfItems = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
    
    pdfDoc.list(myArrayOfItems);
    // Move down a bit to provide space between lists
    pdfDoc.moveDown(0.5);
    
    let innerList = ['Nested Item 1', 'Nested Item 2'];
    let nestedArrayOfItems = ['Example of a nested list', innerList];
    
    pdfDoc.list(nestedArrayOfItems);
    
    pdfDoc.end();
    

    Lo que nos da:

    Fuentes

    PDFKit viene con 14 fuentes est谩ndar que se pueden usar en documentos PDF. Cualquiera de estas fuentes se puede pasar al font() funci贸n de la PDFDocument clase, y encadenado con text():

    pdfDoc.font('Times-Roman').text('A text in Times Roman')
    

    Tambi茅n puede agregar fuentes adicionales pasando la ruta al archivo de fuentes como argumento a la font() funci贸n, as铆 como el nombre de la fuente espec铆fica que desea en caso de que el archivo tenga una colecci贸n de fuentes. Alternativamente, puede darle un nombre a la nueva fuente para que se pueda acceder a ella por ese nombre en lugar de la ruta del archivo:

    pdfDoc.registerFont('Name of the font', '/file_path', 'specific_font_name_in_case_of_a_collection')
    

    Llamadas a font() se puede encadenar con otras funciones, al igual que en el fillColor() ejemplo.

    Tambi茅n puede establecer el tama帽o de fuente mediante el fontSize() funci贸n. Echemos un vistazo a algunos ejemplos:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    let pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('fonts.pdf'));
    
    pdfDoc.font('ZapfDingbats').text('This is a symbolic font.');
    pdfDoc.font('Times-Roman').fontSize(25).fillColor('blue').text('You can set a color for any font');
    pdfDoc.font('Courier').fontSize(5).fillColor('black').text('Some text to demonstrate.');
    
    pdfDoc.end();
    

    Ejecutar esto nos dar铆a el siguiente PDF como resultado:

    Agregar im谩genes

    Otra cosa com煤n que quiz谩s desee agregar a sus archivos PDF son las im谩genes. Puedes llamar al image() funci贸n en la instancia del documento y pasar la ruta o el URI de la imagen que desea incluir.

    Tambi茅n puede establecer opciones como el ancho, alto, alineaci贸n horizontal y vertical de la imagen pasando un objeto que contenga pares clave-valor como argumento a la image() funci贸n. De forma predeterminada, las im谩genes se cargan en su tama帽o original.

    Si configura el width y height – la imagen se estirar谩 para ajustarse a los par谩metros especificados. Si se omite uno de estos, la imagen se escala proporcionalmente al par谩metro proporcionado:

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    let pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('images.pdf'));
    
    pdfDoc.text('By default, the image is loaded in its full size:')
    pdfDoc.image('raspberries.jpg');
    
    pdfDoc.moveDown(0.5)
    pdfDoc.text('Scaled to fit width and height')
    pdfDoc.image('raspberries.jpg', {width: 150, height: 150});
    
    pdfDoc.moveDown(0.5)
    pdfDoc.text('Scaled to fit width')
    pdfDoc.image('raspberries.jpg', {width: 150});
    
    pdfDoc.end();
    

    Ejecutar este c贸digo nos dar铆a:

    Tambi茅n puede escalar la imagen dando un scale factor. Adem谩s, puede dar un fit o cover matriz, donde la imagen se escalar谩 para ajustarse al rect谩ngulo provisto o para cubrirlo, respectivamente. Si proporciona un fit o cover matriz, tambi茅n puede establecer la alineaci贸n horizontal (align) y la alineaci贸n vertical (valign):

    const PDFDocument = require('pdfkit');
    const fs = require('fs');
    
    let pdfDoc = new PDFDocument;
    pdfDoc.pipe(fs.createWriteStream('images.pdf'));
    
    pdfDoc.text('Scaled by a factor, keeps the original proportions:')
    pdfDoc.image('raspberries.jpg', {scale: 0.75});
    
    pdfDoc.moveDown(0.5)
    pdfDoc.text('Fit with horizontal alignment:')
    pdfDoc.image('raspberries.jpg', {fit: [400, 150], align: 'center'});
    
    pdfDoc.end();
    

    Esto nos dar铆a:

    Conclusi贸n

    En este art铆culo hemos visto c贸mo generar archivos PDF en Node.js usando PDFKit. Hemos explorado algunas de las opciones disponibles para formatear texto y c贸mo agregar im谩genes a nuestros archivos. La biblioteca tiene una extensa documentaci贸n que cubre mucho m谩s sobre la creaci贸n de archivos PDF en aplicaciones Node.js.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *