Kako generirati HTML tablicu i PDF s Node i Google Puppeteer

Conoce la tierra.

Interno razumijevanje NodeJS-a može biti pomalo zastrašujuće (znam da je to jednom bilo za mene). Node je vrlo moćan jezik i može učiniti puno stvari.

Danas sam želio otkriti snagu ugrađenog uslužnog alata Node nazvanog fs (datotečni sustav)

Prema fs dokumentima:

fsModul pruža API za interakciju s datotečnog sustava na način usko po uzoru oko standardnih POSIX funkcije.

Što je samo izmišljeni način da se kaže da je sustav datoteka način na koji Node komunicira s datotekama za operacije čitanja i pisanja.

Sada je datotečni sustav nevjerojatan uslužni program u NodeJS-u koji ima puno otmjenih značajki. U ovom ću članku, međutim, razgovarati samo o 3:

  • Dobivanje podataka o datoteci: fs.statSync
  • Brisanje datoteke: fs.unlinkSync
  • Zapisivanje podataka u datoteku: fs.writeFileSync

Još jedna stvar koju ćemo pokriti u ovom članku je Google Puppeteer, što je ovaj stvarno kul, gladak alat koji su stvorili neki sjajni ljudi na Googleu.

Pa što je lutkar? Pa prema dokumentima, kažu:

Puppeteer je Node knjižnica koja pruža API na visokoj razini za kontrolu bezglavog Chromea ili Chroma preko protokola DevTools. Također se može konfigurirati da koristi puni (bezglavi) Chrome ili Chromium.

To je u osnovi alat koji vam omogućuje da na poslužitelju napravite sve cool stvari povezane s preglednikom. Kao što je dobivanje snimaka zaslona web stranice, indeksiranje web stranica i generiranje sadržaja za prethodno prikazivanje za aplikacije na jednoj stranici. Možete čak i slati obrasce putem vašeg NodeJS poslužitelja.

Lutkar je opet ogroman alat, pa ćemo pokriti samo malu, ali vrlo cool osobinu lutkara. Pogledat ćemo kako generirati lijepu PDF datoteku na temelju generirane datoteke HTML tablice. U procesu ćemo naučiti o puppeteer.launch () i razumjeti malo o stranici () i pdf ().

Da bismo opet dali kratki pregled, stvari koje ćemo pokriti:

  • Generiranje podataka o izvorima (za račune) pomoću mrežnog alata.
  • Stvaranje HTML tablice s malo stila s generiranim podacima u njoj, pomoću automatizirane skripte čvora.
  • Učenje o provjeri postoji li datoteka ili ne pomoću fs.statSync
  • Učenje o brisanju datoteke pomoću fs.unlinkSync
  • Učenje o pisanju datoteke pomoću fs.writeFileSync
  • Stvaranje PDF datoteke te HTML datoteke generirane pomoću Google lutkara
  • Pretvaranje u npm skripte, koje će se kasnije koristiti? ?
Također prije nego što započnemo, ovdje je cjelokupni izvorni kôd vodiča, koji svi trebaju slijediti. Ne morate ništa pisati, ali trebali biste napisati kod zajedno s ovim uputstvom. To će se pokazati korisnijim i shvatit ćete više. KOD IZVORA TUTORIJALA

Prije nego što započnemo, pobrinite se da na svoj stroj imate instalirano barem sljedeće

  • Verzija čvora 8.11.2
  • Upravitelj paketa čvorova (NPM) verzija 6.9.0

Ne trebate, ali možete pogledati i uvodni video (moj prvi ikad napravljen) koji govori o osnovama čitanja, pisanja i brisanja datoteke u NodeJS-u. Ovo će vam pomoći da razumijete ovaj vodič. (Molimo da mi date povratne informacije). ?

Započnimo

Korak 1:

U svoj terminal unesite sljedeće:

npm init -y

Ovo će za vas inicijalizirati prazan projekt.

Korak 2:

Drugo, u istoj mapi izradite novu datoteku koja se zove data.jsoni u kojoj se nalaze neki ismijani podaci. Možete koristiti sljedeći JSON uzorak.

Podružene JSON podatke o klatnu možete dobiti odavde . Za generiranje ovih podataka koristio sam sjajan alat nazvan //mockaroo.com/ To je mrežni alat za generiranje podataka.

JSON podaci s kojima idem imaju strukturu poput ove:

[ {}, {}, { "invoiceId": 1, "createdDate": "3/27/2018", "dueDate": "5/24/2019", "address": "28058 Hazelcrest Center", "companyName": "Eayo", "invoiceName": "Carbonated Water - Peach", "price": 376 }, { "invoiceId": 2, "createdDate": "6/14/2018", "dueDate": "11/14/2018", "address": "6205 Shopko Court", "companyName": "Ozu", "invoiceName": "Pasta - Fusili Tri - Coloured", "price": 285 }, {}, {} ]
Kompletni JSON-ov niz za ovaj vodič možete preuzeti ovdje .

Korak 3:

Zatim stvorite novu datoteku pod nazivom buildPaths.js

const path = require('path'); const buildPaths = { buildPathHtml: path.resolve('./build.html'), buildPathPdf: path.resolve('./build.pdf') }; module.exports = buildPaths;

Tako path.resolveće uzeti relativni put i vratiti nam apsolutni put tog određenog direktorija.

Tako path.resolve('./build.html');će na primjer vratiti nešto poput ovoga:

$ C:\\Users\\Adeel\\Desktop\\articles\\tutorial\\build.html

Korak 4:

U istoj mapi izradite datoteku pod nazivom createTable.jsi dodajte sljedeći kod:

const fs = require('fs'); // JSON data const data = require('./data.json'); // Build paths const { buildPathHtml } = require('./buildPaths'); /** * Take an object which has the following model * @param {Object} item * @model * { * "invoiceId": `Number`, * "createdDate": `String`, * "dueDate": `String`, * "address": `String`, * "companyName": `String`, * "invoiceName": `String`, * "price": `Number`, * } * * @returns {String} */ const createRow = (item) => ` ${item.invoiceId}${item.invoiceName}${item.price}${item.createdDate}${item.dueDate}${item.address}${item.companyName} `; /** * @description Generates an `html` table with all the table rows * @param {String} rows * @returns {String} */ const createTable = (rows) => ` 
     ${rows} 
     
Invoice Id Invoice Name Price Invoice Created Due Date Vendor Address Vendor Name
`; /** * @description Generate an `html` page with a populated table * @param {String} table * @returns {String} */ const createHtml = (table) => ` table { width: 100%; } tr { text-align: left; border: 1px solid black; } th, td { padding: 15px; } tr:nth-child(odd) { background: #CCC } tr:nth-child(even) { background: #FFF } .no-content { background-color: red; } ${table} `; /** * @description this method takes in a path as a string & returns true/false * as to if the specified file path exists in the system or not. * @param {String} filePath * @returns {Boolean} */ const doesFileExist = (filePath) => { try { fs.statSync(filePath); // get information of the specified file path. return true; } catch (error) { return false; } }; try { /* Check if the file for `html` build exists in system or not */ if (doesFileExist(buildPathHtml)) { console.log('Deleting old build file'); /* If the file exists delete the file from system */ fs.unlinkSync(buildPathHtml); } /* generate rows */ const rows = data.map(createRow).join(''); /* generate table */ const table = createTable(rows); /* generate html */ const html = createHtml(table); /* write the generated html to file */ fs.writeFileSync(buildPathHtml, html); console.log('Succesfully created an HTML table'); } catch (error) { console.log('Error generating table', error); }

Znam da je to puno koda, ali podijelimo ga na dijelove i počnite ga razumijevati dio po dio.

Idite na red 106 (github suština)

U našem try/catchbloku prvo provjeravamo postoji li datoteka za izgradnju za HTML u sustavu ili ne. Ovo je put datoteke gdje će naša skripta NodeJS generirati naš HTML.

if (doesFileExist(buildPathHtml){}poziva metodu doesFileExist () koja jednostavno vraća true / false. Za ovo koristimo

fs.statSync(filePath);

This method actually returns information about the file like the size of the file, when the file was created, and so on. However if we provide it an invalid file path, this method returns as a null error. Which we use here to our benefit and wrap the fs.statSync() method in a try/catch. If Node is successfully able to read the file in our try block, we return true — otherwise it throws an error which we get in our catch block and returns false.

If the file exists in the system we end up deleting the file using

fs.unlinkSync(filePath); // takes in a file path & deletes it

After deleting the file, we need to generate rows to put in the table.

Step 5:

So first we import data.json which we do at line 3 & then on line 115 we iterate each item using map(). You can read more about Array.prototype.map() here.

The map method takes a method createRow which takes in an object through each iteration and returns a string which has content like this:

"invoice idinvoice nameinvoice priceinvoice created dateinvoice due dateinvoice addressinvoice sender company name"
const row = data.map(createdRow).join('');

The join('') part is important here, because I want to concatenate all of my array into a string.

An almost similar principle is used for generating a table on line 117 & then the html table on line 119.

Step 6:

The important part is where we write to our file on line 121:

fs.writeFileSync(buildPathHtml, html); 

It takes in 2 parameters: one is the build path (string) and the html content (string) and generates a file (if not created; and if it is created, it overwrites the already existing file).

Ovdje treba napomenuti da nam možda neće trebati 4. korak, gdje provjeravamo postoji li datoteka i ako postoji, a zatim je brišemo. To je zato što writeFileSync to čini umjesto nas. Upravo sam to dodao u kod za potrebe učenja.

Korak 7:

U svom terminalu idite na put do mape na kojem imate tipku createTable.jsi

$ npm run ./createTable.js

Čim pokrenete ovu skriptu, stvorit će novu datoteku u istoj mapi pod nazivom build.htmlMožete otvoriti tu datoteku u svom pregledniku i izgledat će otprilike ovako.

Cool zar ne? Zasada je dobro. ?

Također npm scriptu svoj paket.json možete dodati ovako:

"scripts": { "build:table": "node ./createTable.js" },

Na ovaj način, umjesto pisanja npm run ./createTable.js, možete jednostavno upisati npm run build:table.

Sljedeće: generiranje PDF-a iz generirane HTMLdatoteke.

Korak 8:

First things first we need to install a fancy tool, so go in your terminal in your application folder and type in

npm install puppeteer

Step 9:

In the same folder where you have files createTable.js , buildPaths.js & data.json, create a new file called createPdf.js and add content to it like below:

 const fs = require('fs'); const puppeteer = require('puppeteer'); // Build paths const { buildPathHtml, buildPathPdf } = require('./buildPaths'); const printPdf = async () => { console.log('Starting: Generating PDF Process, Kindly wait ..'); /** Launch a headleass browser */ const browser = await puppeteer.launch(); /* 1- Ccreate a newPage() object. It is created in default browser context. */ const page = await browser.newPage(); /* 2- Will open our generated `.html` file in the new Page instance. */ await page.goto(buildPathHtml, { waitUntil: 'networkidle0' }); /* 3- Take a snapshot of the PDF */ const pdf = await page.pdf({ format: 'A4', margin: { top: '20px', right: '20px', bottom: '20px', left: '20px' } }); /* 4- Cleanup: close browser. */ await browser.close(); console.log('Ending: Generating PDF Process'); return pdf; }; const init = async () => { try { const pdf = await printPdf(); fs.writeFileSync(buildPathPdf, pdf); console.log('Succesfully created an PDF table'); } catch (error) { console.log('Error generating PDF', error); } }; init();

As we did with createTable.js script, let’s break this down into chunks and start understanding this script step by step.

Let’s start with line 40: here we call a method init() which calls the method on line 30. Onething to focus on is that our init() method is an async method. Read more on this async function.

Prvo u metodi init () nazivamo metodu printPdf () koja je opet async metoda, pa moramo pričekati njezin odgovor. Metoda printPdf () vraća nam PDF primjerak koji zatim zapisujemo u datoteku u retku 33.

Pa, što printPdf()metoda radi? Kopajmo duboko u to.

const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(buildPathHtml, { waitUntil: 'networkidle0' }); const pdf = await page.pdf({ format: 'A4', margin: { top: '20px', right: '20px', bottom: '20px', left: '20px'} }); await browser.close(); return pdf;

Prvo pokrećemo bezglavu instancu preglednika pomoću lutkarstva radeći sljedeće:

await puppeteer.launch(); // this returns us headless browser

koje zatim koristimo za otvaranje web stranice:

await browser.newPage(); // open a blank page in headless browser

Nakon što otvorimo praznu stranicu, možemo prijeći na stranicu. Budući da je naša web stranica lokalno u našem sustavu, mi jednostavno

page.goto(buildPathHtml, { waitUntil: 'networkidle0' });

Ovdje waitUntil: 'networkidle0;je važno, jer lutkaru govori da pričeka 500 / ms dok više nema mrežnih veza.

Napomena: Zbog toga smo koristili path.resolve () za dobivanje apsolutnih putova, jer da bismo otvorili web stranicu s lutkarom, potreban nam je apsolutni put.

After we have a web page opened in the headless browser on the server, we save that page as a pdf:

await page.pdf({ });

As soon as we have a pdf version of the web page, we need to close the browser instance opened by puppeteer to save resources by doing this:

await browser.close();

& then we return the pdf saved, which we then write to the file.

Step 10:

In your terminal type

$ npm ./createPdf.js

Note: Before running the above script, ensure that you the build.html file generated by createTable.js script. This ensures we always have the build.html prior to running the createPdf.js script. In your package,json do the following.

"scripts": { "build:table": "node ./createTable.js", "prebuild:pdf": "npm run build:table", "build:pdf": "node ./createPdf.js" },

Now if you run $ npm run build:pdf it will execute the createTable.js script first and then createPdf.js script. You can read more on NPM scripts on their official docs.

When you run

$ npm run build:pdf

It will run and create a build.pdf which will look like this:

I to je to, gotovi smo.

Naučili ste sljedeće:

  • Kako provjeriti postoji li datoteka / podaci o datoteci tet (u Nodeu)
  • Kako izbrisati datoteku u Nodeu
  • Kako zapisati u datoteku
  • Kako koristiti Google Puppeteer za generiranje PDF datoteke

Sretno učenje, volio bih čuti vaše misli o ovom članku. Možete me dobiti na Twitterutakođer.