项目需求是把一个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文件加载失败");
}
}
},