目录

vue项目纯前端把PDF转成图片并下载

目录

vue项目纯前端把PDF转成图片并下载

项目需求是把一个pdf转成图片,并在最后添加上二维码,然后下载下来。

经过一番研究以后,作此记录。

主要用到了pdfjs-dist这个包,我用的是2.16.105版本。

废话不多说,直接上代码。

先下载node_modules包

npm i pdfjs-dist -S

然后在vue页面中引入:

import * as pdfjsLib from "pdfjs-dist/legacy/build/pdf.js";
import * as pdfjsWorker from "pdfjs-dist/legacy/build/pdf.worker.entry.js";
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;

下面是在methods里面写的方法:

// 通过前台用pdf转图片
    async pdfForImage(pdf) {
      this.isExportLoad = true; // 控制加载中
      const pdfurl = pdf; // 传过来的是pdf的连接
      console.log(pdfurl, "pdf地址");
      if (pdfurl) {
        try {
            // 读取pdf文件
          const pdfDoc = await pdfjsLib.getDocument(pdfurl).promise;
          const pageNum = pdfDoc.numPages;
          console.log(pageNum, "pdf页数");
          const promiseArr = [];
          // 循环pdf每一页
          for (let i = 1; i <= pageNum; i++) {
            const page = await pdfDoc.getPage(i);
            const viewport = page.getViewport({ scale: 1.5 }); // 设置合适的缩放比例
            // 创建canvas画布
            const canvas = document.createElement("canvas");
            const ctx = canvas.getContext("2d");
            canvas.width = viewport.width;
            canvas.height = viewport.height;
            // 把每一页Pdf画到canvas中
            const renderTask = page.render({
              canvasContext: ctx,
              viewport: viewport,
            });
            // 因为有好多页,所以通过promise完成每一页的canvas画布以后再统一合并图片
            const promise = new Promise((resolve, reject) => {
              // 等待渲染完成
              renderTask.promise
                .then(() => {
                  resolve({
                    canvas,
                    width: canvas.width,
                    height: canvas.height,
                  });
                })
                .catch((error) => {
                  reject({
                    error,
                    canvas: null,
                    width: 0,
                    height: 0,
                  });
                });
            });
            promiseArr.push(promise);
          }
          // 等所有pdf页面渲染完成
          Promise.all(promiseArr).then((res) => {
            console.log(res, "res");
            if (res.length > 0) {
              // 合并canvas并生成图片
              const canvas = document.createElement("canvas");
              const ctx = canvas.getContext("2d");
              // 获取最大宽度
              let width = Math.max(...res.map((item) => item.width));
              // 获取高度总和
              let height = res.reduce((total, item) => total + item.height, 0);
              let num = 0, qrCanvasHeight = 136; // qrCanvasHeight是二维码图片的高度上下预留出20px的间距
              canvas.width = width;
              canvas.height = height + qrCanvasHeight; // 高度要加上二维码图片的高度
              ctx.fillStyle = "#ffffff"; // 给画布加上白色背景,这个色值可以随便更换
              ctx.fillRect(0, 0, width, height + qrCanvasHeight);
              res.forEach((item) => {
                if (item.canvas && item.height > 0) {
                  // 画图片信息
                  ctx.drawImage(item.canvas, 0, num, item.width, item.height);
                  num += item.height;
                }
              });
              // 添加二维码图片
              const img = new Image();
              img.src = require("@/assets/qrcode.png"); // 二维码图片地址
              img.width = 320; // 二维码宽度
              img.height = 96; // 二维码高度
              img.onload = () => {
                ctx.drawImage(
                  img,
                  width / 2 - 160, // 为了让图片左右剧中
                  num + 20, // 让二维码与上方多20px的间距
                  img.width,
                  img.height
                );
                // 把canvas生成图片
                const imageUrl = canvas.toDataURL("image/jpeg", 1); // 我这里是生成为jpg了,也可以传image/png
                // ctx.scale(2, 2); // 可选:放大图像以便查看(根据需要调整)
                // console.log(imageUrl, "imageUrl"); // 生成的base64图片地址,可以输出查看
                // 下载图片
                const link = document.createElement("a");
                link.href = imageUrl;
                link.download = `分析报告.jpg`;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                this.isExportLoad = false;
              };
            }
          });
        } catch (err) {
          console.log(err);
          this.$message.error("pdf文件加载失败");
        }
      }
    },