Node & Google Puppeteer ile bir HTML tablosu ve PDF nasıl oluşturulur?

Conoce la tierra.

NodeJS'yi dahili olarak anlamak biraz ürkütücü olabilir (bir zamanlar bunun benim için olduğunu biliyorum). Düğüm çok güçlü bir dildir ve pek çok şey yapabilir.

Bugün Node'un fs (dosya sistemi) adı verilen yerleşik yardımcı program aracının gücünü ortaya çıkarmak istedim.

Fs belgelerine göre:

fsModül yakından standart POSIX fonksiyonları etrafında modellenmiş bir şekilde dosya sistemi ile etkileşim için bir API sağlar.

Bu, dosya sisteminin Node'da hem okuma hem de yazma işlemleri için dosyalarla etkileşim kurmanın bir yolu olduğunu söylemenin sadece süslü bir yolu.

Şimdi dosya sistemi, NodeJS'de birçok süslü özelliğe sahip muazzam bir yardımcı programdır. Ancak bu yazıda sadece 3'ü tartışacağım:

  • Dosya bilgilerini alma: fs.statSync
  • Bir dosyayı silme: fs.unlinkSync
  • Bir dosyaya veri yazma: fs.writeFileSync

Bu makalede ele alacağımız bir diğer şey de Google'daki bazı harika kişiler tarafından oluşturulan bu gerçekten harika, kaygan araç olan Google Puppeteer.

Peki kuklacı nedir? Dokümanlara göre şöyle diyorlar:

Puppeteer, DevTools Protokolü üzerinden başsız Chrome veya Chromium'u kontrol etmek için üst düzey bir API sağlayan bir Düğüm kitaplığıdır. Tam (başsız) Chrome veya Chromium kullanacak şekilde de yapılandırılabilir.

Yani temelde, tarayıcıyla ilgili tüm harika şeyleri sunucuda yapmanıza izin veren bir araçtır. Bir web sitesinin ekran görüntülerini almak, web sitelerini taramak ve tek sayfalı uygulamalar için önceden oluşturulmuş içerik oluşturmak gibi. NodeJS sunucunuz aracılığıyla form gönderimleri bile yapabilirsiniz.

Yine kuklacı çok büyük bir araçtır, bu yüzden kuklacının sadece küçük ama çok havalı bir özelliğini ele alacağız. Oluşturulan HTML tablo dosyamıza dayalı olarak güzel bir PDF dosyasının nasıl oluşturulacağına bakacağız. Bu süreçte puppeteer.launch () hakkında bilgi edinecek ve page () ve pdf () hakkında biraz bilgi sahibi olacağız.

Tekrar kısa bir özet vermek gerekirse, ele alacağımız şeyler:

  • Çevrimiçi bir araç kullanarak saplama verileri (faturalar için) oluşturma.
  • Otomatik bir düğüm komut dosyası kullanarak, içinde oluşturulan verilerle biraz stil içeren bir HTML tablosu oluşturmak.
  • Bir dosyanın var olup olmadığını kontrol etmeyi öğrenme fs.statSync
  • Fs.unlinkSync kullanarak dosya silme hakkında bilgi edinme
  • Fs.writeFileSync kullanarak dosya yazmayı öğrenme
  • Google kuklacı kullanılarak oluşturulan bu HTML dosyasından bir PDF dosyası oluşturmak
  • Bunları daha sonra kullanılmak üzere npm betikleri haline getirmek mi? ?
Ayrıca, burada başlamadan önce, herkesin takip etmesi için eğiticinin tüm kaynak kodu. Hiçbir şey yazmanıza gerek yok, ancak bu öğretici ile birlikte kod yazmalısınız. Bu daha faydalı olacak ve daha fazlasını anlayacaksınız. EĞİTİMİN KAYNAK KODU

Başlamadan önce, lütfen makinenizde en azından aşağıdakilerin kurulu olduğundan emin olun

  • Düğüm sürümü 8.11.2
  • Düğüm Paketi Yöneticisi (NPM) sürüm 6.9.0

Buna gerek yok, ancak NodeJS'de bir dosyayı okuma, yazma ve silmenin temellerini anlatan bir giriş videosunu da (ilk yaptığım) izleyebilirsiniz. Bu, bu öğreticiyi anlamanıza yardımcı olacaktır. (Lütfen bana geri bildirimde bulunun). ?

Başlayalım

Aşama 1:

Aşağıdakileri terminal türünüzde:

npm init -y

Bu sizin için boş bir proje başlatacaktır.

Adım 2:

İkinci olarak, aynı klasörde adında yeni bir dosya oluşturun data.jsonve içinde bazı alay verileri bulun . Aşağıdaki JSON örneğini kullanabilirsiniz.

Sahte JSON saplama verilerini buradan alabilirsiniz . Bu verileri oluşturmak için //mockaroo.com/ adlı harika bir araç kullandım. Bu bir çevrimiçi veri oluşturma aracıdır.

Birlikte gittiğim JSON verisi şu şekilde bir yapıya sahip:

[ {}, {}, { "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 }, {}, {} ]
Sen bu öğretici için tam JSON dizi indirebilirsiniz burada .

Aşama 3:

Sonra adında yeni bir dosya oluşturun buildPaths.js

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

Böylece path.resolvegöreceli bir yol izleyecek ve bize o dizinin mutlak yolunu döndürecektir.

Öyleyse path.resolve('./build.html');örneğin şöyle bir şey döndürür:

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

4. Adım:

Aynı klasörde adlı bir dosya oluşturun createTable.jsve aşağıdaki kodu ekleyin:

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 IdInvoice NamePriceInvoice CreatedDue DateVendor AddressVendor 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); }

Bunun çok fazla kod olduğunu biliyorum, ama onu parçalara ayıralım ve parça parça anlamaya başlayalım.

106. satıra git (github özeti)

Bizim de try/catchHTML için inşa dosya sisteminde ya da değil varsa bloğun biz ilk kontrol edin. Bu, NodeJS betiğimizin HTML kodumuzu oluşturacağı dosyanın yoludur.

if (doesFileExist(buildPathHtml){}Yalnızca doğru / yanlış döndüren doesFileExist () yöntemini çağırır. Bunun için kullanıyoruz

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).

Burada not etmemiz gereken bir şey, dosyanın var olup olmadığını kontrol ettiğimiz ve varsa sildiğimiz 4. Adıma ihtiyacımız olmayabilir. Bunun nedeni, writeFileSync'in bunu bizim için yapmasıdır. Bunu sadece öğrenme amacıyla koda ekledim.

7. Adım:

Terminalinizde, sahip olduğunuz klasör yoluna gidin createTable.jsve yazın

$ npm run ./createTable.js

Bu betiği çalıştırır çalıştırmaz, aynı klasörde yeni bir dosya oluşturacaktır. build.htmlBu dosyayı tarayıcınızda açabilirsiniz ve böyle bir şeye benzeyecektir.

Güzel değil mi? Çok uzak çok iyi. ?

Ayrıca npm scriptpackage.json dosyanıza şu şekilde bir ekleyebilirsiniz :

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

Bu şekilde yazmak yerine npm run ./createTable.jssadece yazabilirsiniz npm run build:table.

Sıradaki: oluşturulan HTMLdosyadan bir PDF oluşturmak .

8. Adım:

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.

İlk olarak init () yönteminde yine async yöntem olan printPdf () yöntemini çağırıyoruz , bu yüzden yanıtını beklememiz gerekiyor. PrintPdf () yöntemi bize 33. satırdaki bir dosyaya yazdığımız bir PDF örneğini döndürür .

Peki printPdf()yöntem ne işe yarar? Hadi derinlere inelim.

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;

Önce aşağıdakileri yaparak kuklacı kullanarak başsız bir tarayıcı örneği başlatıyoruz:

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

daha sonra bir web sayfasını açmak için kullanıyoruz:

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

Boş bir sayfa açtıktan sonra bir sayfaya gidebiliriz. Web sayfamız sistemimizde yerel olarak yer aldığından,

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

Burada waitUntil: 'networkidle0;önemlidir, çünkü kuklacıya artık ağ bağlantısı kalmayana kadar 500 / ms beklemesini söyler.

Not: Bu yüzden mutlak yollar elde etmek için path.resolve () kullandık çünkü web sayfasını kuklacı ile açmak için mutlak bir yola ihtiyacımız var.

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:

Ve işte bu, bitirdik.

Aşağıdakileri öğrendiniz:

  • Bir dosyanın mevcut olup olmadığı / tet dosyası bilgisi nasıl kontrol edilir (Düğümde)
  • Düğümdeki bir dosya nasıl silinir
  • Bir dosyaya nasıl yazılır
  • Bir PDF dosyası oluşturmak için Google Puppeteer nasıl kullanılır?

Mutlu öğrenmeler, bu yazı hakkındaki düşüncelerinizi duymak isterim. Bana twitter üzerinden ulaşabilirsinizyanı sıra.