Bahan, terjemahan yang kami terbitkan hari ini, dikhususkan untuk pembuatan file-file PDF dinamis menggunakan kode-HTML sebagai templat. Yaitu, kita akan berbicara tentang cara membuat faktur sederhana untuk pembayaran barang atau jasa tertentu, data dinamis yang termasuk di dalamnya diambil dari keadaan aplikasi Bereaksi. Basis aplikasi Bereaksi dibuat menggunakan create-react-app, bagian server dari proyek didasarkan pada Node.js, dan kerangka kerja Express digunakan dalam pengembangannya.

Penulis materi ini mencatat bahwa ia menyiapkan
video yang menunjukkan perkembangan proyek. Jika Anda memutuskan untuk menonton video dan membaca artikel, disarankan untuk melakukannya. Pertama, membaca sepintas lalu artikel tersebut, lalu nyalakan video dan buat ulang sistem yang Anda pertimbangkan di sana. Setelah itu, baca saja artikelnya.
Pembuatan proyek
Buat direktori proyek dan buka:
mkdir pdfGenerator && cd pdfGenerator
Buat aplikasi Bereaksi baru:
create-react-app client
Setelah menyelesaikan pembuatan aplikasi, buka direktori yang baru saja Anda buat dan instal dependensi:
cd client && npm i -S axios file-saver
Buat server Express. Untuk melakukan ini, buat folder
server
di direktori proyek dan pergi ke sana. Di dalamnya, buat file
index.js
dan mulai inisialisasi proyek:
mkdir server && cd server && touch index.js && npm init
Di sini, untuk membentuk
package.json
, cukup tekan
Enter
beberapa kali. Setelah itu, jalankan perintah berikut untuk menambahkan dependensi yang diperlukan ke bagian server proyek:
npm i -S express body-parser cors html-pdf
Sekarang, di file
client/package.json
, di atas bagian deskripsi dependensi, tambahkan berikut ini:
"proxy": "http://localhost:5000/"
Ini akan membantu bekerja dengan server lokal dari kode klien.
Sekarang Anda perlu membuka dua jendela terminal.
Di jendela pertama, buka direktori
client
dan jalankan perintah berikut:
npm start
Di jendela kedua, buka folder
server
dan jalankan perintah berikut:
nodemon index.js
Penyiapan klien awal
Bagian klien dari proyek kami akan terlihat sangat sederhana.
Pertama, di file
src/App.js
bagian klien dari aplikasi, kami mengimpor dependensi ke dalam kode:
import axios from 'axios'; import { saveAs } from 'file-saver';
Setelah itu, di bagian atas deskripsi komponen, inisialisasi keadaan:
state = { name: 'Adrian', receiptId: 0, price1: 0, price2: 0, }
Mari kita hapus markup JSX standar yang dibuat dalam templat aplikasi menggunakan
create-react-app
dan kembali dari metode
render()
. Masukkan yang berikut ini ke dalamnya:
<div className="App"> <input type="text" placeholder="Name" name="name" onChange {this.handleChange}/> <input type="number" placeholder="Receipt ID" name="receiptId" onChange={this.handleChange}/> <input type="number" placeholder="Price 1" name="price1" onChange={this.handleChange}/> <input type="number" placeholder="Price 2" name="price2" onChange={this.handleChange}/> <button onClick={this.createAndDownloadPdf}>Download PDF</button></div>
Mari kita buat metode
handleChange
, yang akan bertanggung jawab untuk memperbarui data status aplikasi yang terkait dengan bidang input:
handleChange = ({ target: { value, name }}) => this.setState({ [name]: value })
Sekarang kita dapat beralih ke tugas membuat file PDF. Bagian itu, yang diselesaikan dengan cara klien, adalah membuat permintaan POST ke server. Permintaan mengirim status aplikasi:
createAndDownloadPdf = () => { axios.post('/create-pdf', this.state) }
Sebelum kami terus bekerja di sisi klien proyek, kami perlu mengkonfigurasi rute di server. Ini akan memungkinkan server untuk menerima data dari klien, menghasilkan file PDF dan mentransfer file ini kembali ke klien.
Penyiapan server awal
Bagian server dari proyek hanya akan mencakup dua rute. Diperlukan satu untuk membuat PDF. Yang kedua adalah untuk mengirim file ke klien.
Pertama, impor dependensi ke file
index.js
:
const express = require('express'); const bodyParser = require('body-parser'); const pdf = require('html-pdf'); const cors = require('cors');
Kami menginisialisasi aplikasi Express dan mengkonfigurasi port:
const app = express(); const port = process.env.PORT || 5000;
Menyiapkan parser kueri. Apa yang kita butuhkan akan tersedia sebagai
req.body
. Kami juga akan mengonfigurasi CORS sehingga kesalahan
Cross-Origin Request Blocked
kami tidak mengganggu pekerjaan kami:
app.use(cors()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());
Setelah itu, jalankan server:
app.listen(port, () => console.log(`Listening on port ${port}`));
Sekarang kita dapat menangani kode yang bertanggung jawab untuk membuat PDF.
Buat template HTML untuk PDF
Kami membutuhkan template HTML untuk digunakan saat membuat file PDF. Dalam membuat templat seperti itu, kemungkinan tak terbatas membuka di hadapan kita. Segala sesuatu yang dapat dibuat menggunakan HTML dan CSS murni dapat direpresentasikan sebagai file PDF. Buat direktori
documents
di folder
server
, buka dan buat file
index.js
di dalamnya:
mkdir documents && cd documents && touch index.js
Dari file ini, kami mengekspor fungsi panah yang akan mengembalikan semua kode HTML yang diperlukan. Saat memanggil fungsi ini, Anda dapat menggunakan parameter, yang juga akan kami jelaskan di sini.
module.exports = ({ name, price1, price2, receiptId }) => { ... }
Di sini saya akan memberi Anda
contoh template HTML, dan Anda cukup menyalinnya ke proyek Anda. Tetapi Anda, tentu saja, dapat membuat template Anda sendiri.
Mari kita
index.js
kode
index.js
dari folder
server/documents
ke formulir berikut:
module.exports = ({ name, price1, price2, receiptId }) => { const today = new Date(); return ` <!doctype html> <html> <head> <meta charset="utf-8"> <title>PDF Result Template</title> <style> .invoice-box { max-width: 800px; margin: auto; padding: 30px; border: 1px solid #eee; box-shadow: 0 0 10px rgba(0, 0, 0, .15); font-size: 16px; line-height: 24px; font-family: 'Helvetica Neue', 'Helvetica', color: #555; } .margin-top { margin-top: 50px; } .justify-center { text-align: center; } .invoice-box table { width: 100%; line-height: inherit; text-align: left; } .invoice-box table td { padding: 5px; vertical-align: top; } .invoice-box table tr td:nth-child(2) { text-align: right; } .invoice-box table tr.top table td { padding-bottom: 20px; } .invoice-box table tr.top table td.title { font-size: 45px; line-height: 45px; color: #333; } .invoice-box table tr.information table td { padding-bottom: 40px; } .invoice-box table tr.heading td { background: #eee; border-bottom: 1px solid #ddd; font-weight: bold; } .invoice-box table tr.details td { padding-bottom: 20px; } .invoice-box table tr.item td { border-bottom: 1px solid #eee; } .invoice-box table tr.item.last td { border-bottom: none; } .invoice-box table tr.total td:nth-child(2) { border-top: 2px solid #eee; font-weight: bold; } @media only screen and (max-width: 600px) { .invoice-box table tr.top table td { width: 100%; display: block; text-align: center; } .invoice-box table tr.information table td { width: 100%; display: block; text-align: center; } } </style> </head> <body> <div class="invoice-box"> <table cellpadding="0" cellspacing="0"> <tr class="top"> <td colspan="2"> <table> <tr> <td class="title"><img src="https://i2.wp.com/cleverlogos.co/wp-content/uploads/2018/05/reciepthound_1.jpg?fit=800%2C600&ssl=1" style="width:100%; max-width:156px;"></td> <td> Datum: ${`${today.getDate()}. ${today.getMonth() + 1}. ${today.getFullYear()}.`} </td> </tr> </table> </td> </tr> <tr class="information"> <td colspan="2"> <table> <tr> <td> Customer name: ${name} </td> <td> Receipt number: ${receiptId} </td> </tr> </table> </td> </tr> <tr class="heading"> <td>Bought items:</td> <td>Price</td> </tr> <tr class="item"> <td>First item:</td> <td>${price1}$</td> </tr> <tr class="item"> <td>Second item:</td> <td>${price2}$</td> </tr> </table> <br /> <h1 class="justify-center">Total price: ${parseInt(price1) + parseInt(price2)}$</h1> </div> </body> </html> `; };
server/index.js
menyertakan file ini dalam file
server/index.js
:
const pdfTemplate = require('./documents');
Buat PDF
Ingatlah bahwa di server kita akan membuat dua rute. Rute POST akan bertanggung jawab untuk menerima data dari klien dan membuat file PDF. Rute GET akan digunakan untuk mengirim file yang sudah selesai ke klien.
β buat-pdf rute
Dalam rute POST
create-pdf
, kita akan menggunakan perintah
pdf.create()
, merujuk pada objek yang diimpor dari modul
html-pdf
.
Sebagai parameter pertama metode
pdf.create()
, templat HTML digunakan, serta data yang diterima dari klien.
Untuk mengembalikan
pdf.create()
, kami memanggil metode
toFile()
, memberikannya nama yang ingin kami tetapkan ke dokumen PDF, serta fungsi panah panggilan balik. Fungsi ini, jika terjadi kesalahan, akan menjalankan perintah
res.send(Promise.reject())
. Jika semuanya berjalan dengan baik, dia akan menjalankan perintah
res.send(Promise.resolve())
.
app.post('/create-pdf', (req, res) => { pdf.create(pdfTemplate(req.body), {}).toFile('result.pdf', (err) => { if(err) { res.send(Promise.reject()); } res.send(Promise.resolve()); }); });
βMengambil-pdf Rute
Pada saat yang sama, kami akan membuat rute yang akan digunakan setelah, atas permintaan klien, file PDF berhasil dibuat. Di sini kita hanya mengambil dokumen yang sudah jadi dan mengirimkannya ke klien menggunakan
res.sendFile()
:
app.get('/fetch-pdf', (req, res) => { res.sendFile(`${__dirname}/result.pdf`) })
Fungsi klien membuatAndDownloadPdf
Sekarang kita dapat kembali ke kode klien dan terus bekerja pada fungsi
createAndDownloadPdf
. Di sini kita membuat permintaan POST ke server menggunakan modul
axios
. Sekarang fungsi ini terlihat seperti ini:
createAndDownloadPdf = () => { axios.post('/create-pdf', this.state) }
Jika setelah menjalankan permintaan POST ke server, dokumen PDF telah dibuat, kami perlu menjalankan permintaan GET, sebagai respons server akan mengirim dokumen yang sudah selesai ke klien.
Untuk menerapkan skema perilaku ini, kami, setelah memanggil
axios.post()
, memanggil.
then()
. Ini memungkinkan kami melakukan itu sebagai tanggapan terhadap permintaan POST klien, kami mengembalikan janji dari server yang dapat berhasil diselesaikan atau ditolak.
Kami melengkapi fungsi dengan kode berikut:
.then(() => axios.get('/fetch-pdf', { responseType: 'blob' })) .then(( res) => {})
Di sini Anda dapat memperhatikan fakta bahwa
blob
digunakan sebagai jenis
responseType
. Sebelum kita melangkah lebih jauh, mari kita bicara tentang apa itu.
Benda gumpalan
Blob adalah objek abadi yang mewakili beberapa data mentah. Objek seperti itu sering digunakan untuk bekerja dengan data yang mungkin tidak dalam format JavaScript asli. Objek tersebut adalah urutan byte yang menyimpan, misalnya, file data. Tampaknya objek
Blob
menyimpan tautan ke file, tetapi kenyataannya tidak. Objek-objek ini menyimpan data yang dapat Anda gunakan. Misalnya - mereka dapat disimpan ke file.
Penyelesaian Proyek
Sekarang kita tahu apa objek
Blob
, kita bisa menggunakan panggilan
.then()
untuk
res.data
objek
Blob
baru di dalamnya, berdasarkan res.data. Saat membuat objek ini, kami akan meneruskan parameter ke konstruktornya, menunjukkan bahwa data yang akan disimpan oleh objek adalah dari type
application/pdf
. Setelah itu, kita dapat menggunakan metode
saveAs()
, yang diimpor dari modul
file-saver
, dan menyimpan data ke file. Akibatnya, kode metode
createAndDowndloadPdf
akan terlihat seperti yang ditunjukkan di bawah ini:
createAndDownloadPdf = () => { axios.post('/create-pdf', this.state) .then(() => axios.get('fetch-pdf', { responseType: 'blob' })) .then((res) => { const pdfBlob = new Blob([res.data], { type: 'application/pdf' }); saveAs(pdfBlob, 'newPdf.pdf'); }) }
Seperti inilah tampilan antarmuka browser.
Aplikasi di browserSetelah mengisi kolom dan mengklik tombol
Download PDF
, data ditransfer ke server dan dokumen PDF diunduh dari sana.
Unduh PDFDan di sini adalah dokumen PDF itu sendiri.
Perangkat Lunak Menghasilkan PDFRingkasan
Kami melihat mekanisme yang memungkinkan Anda membuat file PDF secara terprogram.
Ini adalah repositori GitHub dengan kode proyek. Kami berharap bahwa ide-ide yang Anda temui dalam materi ini akan menemukan aplikasi dalam pengembangan Anda.
Pembaca yang budiman! Bagaimana cara Anda menyelesaikan masalah pemrograman file PDF menggunakan Node.js?