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

Summary of xhtml block level tags

* address - address * blockquote - block quote * c...

Organize the common knowledge points of CocosCreator

Table of contents 1. Scene loading 2. Find Node 1...

Nginx proxy axios request and precautions

Preface I recently wrote a small demo. Because I ...

Example of using mycat to implement MySQL database read-write separation

What is MyCAT A completely open source large data...

A record of the pitfalls of the WeChat applet component life cycle

The component lifecycle is usually where our busi...

JS asynchronous execution principle and callback details

1. JS asynchronous execution principle We know th...

How to set static IP for Ubuntu 18.04 Server

1. Background Netplan is a new command-line netwo...

Tutorial diagram of installing centos7.3 on vmware virtual machine

VMware Preparation CentOS preparation, here is Ce...

Vue component library ElementUI implements table loading tree data tutorial

ElementUI implements a table tree list loading tu...

Detailed usage of kubernetes object Volume

Overview Volume is the abstraction and virtualiza...

Vue implements file upload and download functions

This article example shares the specific code of ...

A brief discussion on MySQL temporary tables and derived tables

About derived tables When the main query contains...