How to generate PDF and download it in Vue front-end

How to generate PDF and download it in Vue front-end

Idea: Convert the HTML page into an image through html2canvas, and then generate the base64 of the image into a pdf file through jspdf.

1. Installation and introduction

//Convert the page html into an image npm install html2canvas --save  
// Generate a pdf from the image
npm install jspdf --save

Introduce the defined implementation method and register it in the main file main.js of the project

import htmlToPdf from '@/utils/htmlToPdf';
// Using the Vue.use() method will call the install method in the tool method Vue.use(htmlToPdf);

Portal: Principle and usage of Vue.use() in Vue

2. How to package and export PDF files

Configuration details

let pdf = new jsPDF('p', 'pt', [pdfX, pdfY]);
The first parameter: l: horizontal p: vertical The second parameter: measurement unit ("pt", "mm", "cm", "m", "in" or "px");
The third parameter: can be in the following format, the default is "a4". For a custom format, just pass the size as a numeric array, like: [592.28, 841.89];
		   a0 - a10
		   b0 - b10
		   c0 - c10
  		   dl
		   letter
		   government-letter
		   legal
		   junior-legal
		   ledger
		   tabloid
		   credit card

pdf.addPage() adds a new page to the PDF document, the default size is a4. The parameters are as follows:

pdf.addImage() adds an image to the PDF. The parameters are as follows:

Delete a page of pdf

let targetPage = pdf.internal.getNumberOfPages(); //Get the total pages pdf.deletePage(targetPage); //Delete the target page

Save pdf document

pdf.save(`test.pdf`);

Encapsulate the method of exporting pdf files (utils/htmlToPdf.js)

// Export the page to PDF format import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default{
  install (Vue, options) {
    Vue.prototype.getPdf = function () {
      // When downloading PDF, if it is not at the top of the page, the PDF style will be incorrect, so go back to the top of the page and then download let top = document.getElementById('pdfDom');
      if (top != null) {
        top.scrollIntoView();
        top = null;
      }
      let title = this.exportPDFtitle;
      html2Canvas(document.querySelector('#pdfDom'), {
        allowTaint: true
      }).then(function (canvas) {
        // Get the width and height of the canvas let contentWidth = canvas.width;
        let contentHeight = canvas.height;
	      // The height of the canvas generated by a pdf page displaying the html page;
        let pageHeight = contentWidth / 841.89 * 592.28;
	      //Height of HTML page without PDF generation let leftHeight = contentHeight;
	      // Page offset let position = 0;
	      // The width and height of the canvas image generated by the HTML page in the PDF (in this case: horizontal A4 paper [841.89, 592.28], the vertical size needs to be changed)
        let imgWidth = 841.89;
        let imgHeight = 841.89 / contentWidth * contentHeight;
        let pageData = canvas.toDataURL('image/jpeg', 1.0);
        let PDF = new JsPDF('l', 'pt', 'a4');
        // Two heights need to be distinguished: one is the actual height of the HTML page, and the other is the height of the generated PDF page. // When the content does not exceed the range of one PDF page, no paging is required if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight;
            position -= 592.28;
            // Avoid adding blank pages if (leftHeight > 0) {
              PDF.addPage();
            }
          }
        }
        PDF.save(title + '.pdf')
      })
    }
  }
}

Application in related components

<template>
  <div class="wrap" >
    <div id="pdfDom" style="padding: 10px;">
      <el-table
        :data="tableData"
        border>
        <el-table-column prop="date" label="Date" width="250"></el-table-column>
        <el-table-column prop="name" label="姓名" width="250"></el-table-column>
        <el-table-column prop="address" label="Address"></el-table-column>
      </el-table>
    </div>
    <button type="button" style="margin-top: 20px;" @click="btnClick">Export PDF</button>
  </div>

</template>
 
<script>
export default {
  data() { 
    return {
      exportPDFtitle: "Page export PDF file name",
      tableData: [
         {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'Huoju Avenue, Jiulongpo District, Chongqing'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'Huoju Avenue, Jiulongpo District, Chongqing'
        },{
          date: '2016-05-03',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-02',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-04',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-01',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-08',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-01',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-08',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'Jiangjun Avenue, Jiangning District, Nanjing'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'Jiangjun Avenue, Jiangning District, Nanjing'
        },, {
          date: '2016-05-04',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-01',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-08',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        },{
          date: '2016-05-01',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-08',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'No. 1518, Jinshajiang Road, Putuo District, Shanghai'
        }, {
          date: '2016-05-08',
          name: 'Wang Xiaohu',
          address: 'Cultural Avenue, Hongshan District, Wuhan'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'Cultural Avenue, Hongshan District, Wuhan'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'Cultural Avenue, Hongshan District, Wuhan'
        }, {
          date: '2016-05-06',
          name: 'Wang Xiaohu',
          address: 'Jiangjun Avenue, Jiangning District, Nanjing'
        }, {
          date: '2016-05-07',
          name: 'Wang Xiaohu',
          address: 'Cultural Avenue, Hongshan District, Wuhan'
        },
      ]
    } 
  }, 
  methods: {
    btnClick(){
      this.$nextTick(() => {this.getPdf();})
    },
  },  
}
</script>  

Effect

Parts to be optimized

  1. When paging, the page content is truncated (welcome to leave a message for discussion);
  2. Different content starts on a new page; Idea: calculate the excess content and occupy the height of the last page (set spacing = page height - excess height).

Summarize

This is the end of this article about how to generate PDF and download in Vue front-end. For more relevant content about generating PDF and downloading in Vue front-end, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue implements PDF export to solve problems such as blurry generated canvas (recommended)
  • How to implement PDF file preview in Vue
  • Vue implements online preview of PDF files and downloading (pdf.js)
  • Detailed explanation of PDF of Vue2.0 global components
  • Vue implements online preview function of PDF document
  • Print web pages to pdf example code in vue
  • Vue exports the page as an image or PDF
  • Implementation ideas of Vue exporting pages to PDF format
  • Detailed explanation of how to use vue-pdf in vue
  • How to export Vue pages into PDF files

<<:  Nginx access log and error log parameter description

>>:  HTML input file control limits the type of uploaded files

Recommend

Ajax responseText parses json data case study

Solve the problem that the responseText returned ...

vue+element custom query component

This article mainly introduces the Vue project. O...

The One-Hand Rule of WEB2.0

<br />My previous article about CSS was not ...

Detailed explanation of how to use WeChat mini program map

This article example shares the specific implemen...

Install MySQL 5.7 on Ubuntu 18.04

This article is compiled with reference to the My...

Detailed explanation of soft links and hard links in Linux

Table of contents 1. Basic storage of files and d...

Vue implements websocket customer service chat function

This article mainly introduces how to implement a...

How to use module fs file system in Nodejs

Table of contents Overview File Descriptors Synch...

Troubleshooting the reasons why MySQL deleted records do not take effect

A record of an online MySQL transaction problem L...

Detailed explanation of VueRouter routing

Table of contents vue router 1. Understand the co...

The most convenient way to build a Zookeeper server in history (recommended)

What is ZooKeeper ZooKeeper is a top-level projec...

JavaScript implements fireworks effects with sound effects

It took me half an hour to write the code, and th...

Nginx configuration and compatibility with HTTP implementation code analysis

Generate SSL Key and CSR file using OpenSSL To co...

Vue custom v-has instruction to implement button permission judgment

Application Scenario Taking the background manage...

A possible bug when MySQL executes the sum function on the window function

When using MySql's window function to collect...