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文件加载失败");
        }
      }
    },
相关推荐
清幽竹客2 分钟前
vue-37(模拟依赖项进行隔离测试)
前端·vue.js
vvilkim2 分钟前
Nuxt.js 页面与布局系统深度解析:构建高效 Vue 应用的关键
前端·javascript·vue.js
paopaokaka_luck5 分钟前
基于SpringBoot+Vue的电影售票系统(协同过滤算法)
vue.js·spring boot·后端
滿6 分钟前
Vue3 父子组件表单滚动到校验错误的位置实现方法
前端·javascript·vue.js
夏梦春蝉1 小时前
ES6从入门到精通:模块化
前端·ecmascript·es6
拓端研究室2 小时前
视频讲解:门槛效应模型Threshold Effect分析数字金融指数与消费结构数据
前端·算法
工一木子3 小时前
URL时间戳参数深度解析:缓存破坏与前端优化的前世今生
前端·缓存
半点寒12W5 小时前
微信小程序实现路由拦截的方法
前端
某公司摸鱼前端5 小时前
uniapp socket 封装 (可拿去直接用)
前端·javascript·websocket·uni-app
要加油哦~6 小时前
vue | 插件 | 移动文件的插件 —— move-file-cli 插件 的安装与使用
前端·javascript·vue.js