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

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

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

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

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

先下载node_modules包

javascript 复制代码
npm i pdfjs-dist -S

然后在vue页面中引入:

javascript 复制代码
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里面写的方法:

javascript 复制代码
// 通过前台用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文件加载失败");
        }
      }
    },
相关推荐
hyyyyy!4 分钟前
《从事件冒泡到处理:前端事件系统的“隐形逻辑”》
前端·javascript·react.js
A-Kamen12 分钟前
前端数据模拟利器 Mock.js 深度解析
开发语言·前端·javascript
FG.17 分钟前
React
前端·react.js·前端框架
青红光硫化黑19 分钟前
React基础之ReactRouter
前端·react.js·前端框架
小华同学ai24 分钟前
7.9K star!跨平台开发从未如此简单,这个开源框架让APP开发效率飙升!
前端·后端·github
W起名有点难36 分钟前
前端学习——CSS
前端·css·学习
关山月1 小时前
18 个最佳 React UI 组件库
前端
挣扎与觉醒中的技术人1 小时前
【技术干货】三大常见网络攻击类型详解:DDoS/XSS/中间人攻击,原理、危害及防御方案
前端·网络·ddos·xss
zeijiershuai2 小时前
Vue框架
前端·javascript·vue.js
写完这行代码打球去2 小时前
没有与此调用匹配的重载
前端·javascript·vue.js