The user fills out the form and clicks to save, and can directly download the pdf document.
Solution Server generationIdeas
Google Chrome developed its own Chrome Headless feature in 2017 and launched puppeteer at the same time. It can be understood as a browser that has no interface but can complete the server functional features.
So we can start the puppeteer browser on the server, open the destination URL, and use the conversion function provided by the Chrome browser to convert html to PDF.
Core code generation on the serverFirst, you need to install puppeteer. There may be errors in the npm installation. It is best to use cnpm Taobao image to install it.
Enter cnpm i puppeteer -S installation dependencies.
To create a js file, you only need to open the URL with the puppeteer browser and save the pdf.
// html2pdf.jsconst puppeteer = require('puppeteer');(async function(){ // Start the service const browser = await puppeteer.launch(); // Open the tab const page = await browser.newPage(); // Go to the address await page.goto('https://koa.bootcss.com/#context'); // Turn on the html page and save it to path await page.pdf({path:test.pdf,format:'A4'}) // Close the browser await browser.close();})(); Then enter node html2pdf.js on the console to start the service.
Of course, module.export can also export the module method according to business logic.
shortcoming
Unable to save dynamic data on the form
Since it is a request page from the server, if the user input is not saved on the request address, the cut-out pdf will be the initial state where the page has not been filled in.
In other words, it can only convert static pages because our needs have a lot of user input, so pass.
Client generates core codeIdeas
shortcoming
distortion.
We can clearly find that since it is similar to inserting the screenshot into a pdf on a page, the resolution and configuration of the page are likely to affect the quality of the output image.
At the same time, because it is a screenshot, the page link and other functions may be lost.
Text cutoff
When the canvas canvas is larger than one page size of pdf, the output will be errored. At this time, we need to determine whether the canvas canvas exceeds the A4 size. If it exceeds the canvas, segment the canvas and insert it into a different page.
The problem comes again at this time. Since it is splitting the picture, it is likely that the picture or text will be truncated from half, because we cannot analyze the structure of the canvas internal item.
Core code
Our needs have no pictures and links, so the distortion problem has little impact on us. At the same time, our form consists of multiple items of duplicate equal length, and these items are very short and will not exceed one piece of A4 paper (although this is not rigorous, if necessary, you can get the width and height of the DOM element and cut according to the height of the DOM element).
So I plan to directly divide the canvas according to the item, and save each item to a page of A4 paper.
Several core approaches need to be understood before you start:
html2canvas
// DOM is the DOM node to be converted html2canvas(DOM,{ backgroundColor:#ffffff, width:width, height:height, scale:2, allowTaint:true, }).then((canvas)=>{ // canvas is the canvas after successful conversion})jsPDF
// Create an instance let pdf = new jsPDF('','pt','a4'); // Add the image to the pdf file// The first parameter is the file (base64) format to be inserted, the second is the file format// The third and fourth are the coordinates in the upper left corner of the picture, and the last two are the width and height of the picture after inserting the picture pdf.addImage(image,'JPEG',10,10,height,width); // Add a new page pdf.addPage() // Save the pdf file pdf.save()canvas
// canvas is the image to be cut// sx, sy is the coordinates to start cropping// swidth and sHeight are the width and height of cropping// dx and dy are the coordinates inserted in the image after cropping// sWidth, sHeight is the width and height of the image after cropping cxt.drawImage(canvas, sx, sy, sWidth, sHeight, dx, dy, sWidth, sHeight);
/** * @description: Form to pdf file* @return: pdf */onSubmit(){ // This is the form I want to convert, there are many similar tables in it let form = this.$refs.form; // Get the width and height of the element let width = form.getBoundingClientRect().width; let height = form.getBoundingClientRect().height; html2canvas(form,{ backgroundColor:#ffffff, width:width, height:height, scale:2, allowTaint:true, }).then((canvas)=>{ let pdf = new jsPDF('','pt','a4'); // Perform image cutting let canvasList = this.splitCanvas(canvas,this.forms.length); // traverse the canvas list and add an image per page canvasList.forEach((item,index)=>{ // Convert the image format to base64 let itemImage = item.toDataURL('image/jpeg',1.0); // Reserve 10px margin, the width of A4 paper is 595px on a 72-resolution monitor pdf.addImage(itemImage,'JPEG',10,10,575.28,575.28/item.width*item.height); // If it is not the last page, pagination index == this.forms.length-1 ? '' : pdf.addPage(); }) // File save let blob = pdf.output('blob'); pdf.save('test.pdf'); })},/** * @description: Cut canvas* @param {number} num Number of slices* @param {canvas} canvas * @return {array} canvas list*/splitCanvas(canvas,num){ let height = canvas.height,width = canvas.width; let chunkHeight = height/num;// The height of each slice let chunkList = [];// Storing the result canvas for(let i=0; i<height ; i+=chunkHeight){ // Initialize the position of the crop rectangle box let sx = 0,sy = i,sWidth = width,sHeight = chunkHeight,dx = 0, dy = 0; // Create a canvas node let canvasItem =document.createElement(canvas); // Initialize the canvas size canvasItem.height = chunkHeight; canvasItem.width = width; let cxt = canvasItem.getContext(2d); // Put the cropped image to the new canvas node cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight); chunkList.push(canvasItem); } return chunkList;}, Final effectThe page after the form is saved
The effect of converting to pdf
This is the article about the pure client and pure server implementation solution of HTML to PDF. For more related HTML to PDF content, please search for previous articles from Wulin.com or continue to browse the related articles below. I hope everyone will support Wulin.com in the future!