版本
vue : 2.6.12
pdf-dist: ^2.5.207
node : 14.18.2
背景
公司项目node版本较低, pdf-dist由于新版本的语法较新,项目不支持, 故选择一个低版本的pdf-dist
不同版本的pdf-dist的引入路径可能不同, 注意分辨
低版本的如下 :
import * as pdfjsLib from 'pdfjs-dist';
import * as PdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
注意PdfjsWorker一定要引入, 即使没有显式的引用
步骤
pdf 转图片的 步骤如下, 这里我把pdf全都绘制成了一张图
- 获取文件对象
- 转换为arrayBuffer, 使用pdf-dist加载
- pdf-dist开始渲染, 并且用canvas绘制
- 拿到canvas的base64数据转换返回file对象 (视自己业务而定)
file转arrayBuffer
const fileToArrayBuffer = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = (error) => {
reject(error);
};
reader.readAsArrayBuffer(file);
});
};
base64转换为file对象
function base64ToFile(base64Data, filename) {
// 分割base64的元数据和二进制数据
const arr = base64Data.split(',');
// 提取文件类型 例如 : image/jpeg
const mime = arr[0].match(/:(.*?);/)[1];
// 将base64编码格式解码为原始的二进制
const bstr = atob(arr[1]);
//用来存储解码后的二进制数据
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
// new File(bits, name, options) // bits: `ArrayBuffer`、`Blob`、`Uint8Array`
return new File([u8arr], filename, { type: mime });
}
前提知识点提要
pdf-dist 官方示例 : mozilla.github.io/pdf.js/exam…
pdf-dist api文档 : mozilla.github.io/pdf.js/api/…
pdf-dist api:
-
获取文档实例 : await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
-
getPage(index) 获取pdf的指定页
-
canvas.getContext('2d'); 用于绘制canvas2d图像
-
page.render() 接受一个对象, 包含 canvas和pdf的viewport
-
drawImage: canvas,横坐标, 纵坐标
-
toDataURL: canvas的方法
代码实现
import * as pdfjsLib from 'pdfjs-dist';
import * as PdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
import system from '@/api/modules/system'; // 导入你定义的 API 对象
// 辅助函数:将 File 对象转换为 ArrayBuffer
const fileToArrayBuffer = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
console.log("File successfully read into ArrayBuffer:", reader.result);
resolve(reader.result);
};
reader.onerror = (error) => {
console.error("Error reading file:", error);
reject(error);
};
reader.readAsArrayBuffer(file);
});
};
const pdfConvertImg = async function(file) {
try {
// 将 File 转换为 ArrayBuffer
const arrayBuffer = await fileToArrayBuffer(file);
// 调试信息:确保 arrayBuffer 是有效的
if (!arrayBuffer || arrayBuffer.byteLength === 0) {
throw new Error("Invalid ArrayBuffer: file may be empty or corrupted.");
}
// 从 ArrayBuffer 加载 PDF
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
const canvases = [];
let totalHeight = 0;
let maxWidth = 0;
// 渲染每一页并计算总高度和最大宽度
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
const page = await pdf.getPage(pageNum);
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext = {
canvasContext: context,
viewport: viewport,
};
await page.render(renderContext).promise;
canvases.push(canvas);
totalHeight += viewport.height;
maxWidth = Math.max(maxWidth, viewport.width);
}
// 创建一个新的 canvas 来合并所有页面
const finalCanvas = document.createElement('canvas');
finalCanvas.width = maxWidth;
finalCanvas.height = totalHeight;
const finalContext = finalCanvas.getContext('2d');
let currentHeight = 0;
for (let canvas of canvases) {
finalContext.drawImage(canvas, 0, currentHeight);
currentHeight += canvas.height;
}
// 将合并后的 canvas 转换为 Base64 图片
const base64Image = finalCanvas.toDataURL('image/png');
// 将 Base64 图片转换为 File 对象
const fileResult = base64ToFile(base64Image, 'mergedImage.png');
// 创建 FormData 并将文件对象附加到请求中
const formData = new FormData();
formData.append('file', fileResult);
formData.append('businessType', '0');
// 上传文件并返回结果 URL,使用导入的 API 对象进行文件上传
return await system.file.uploadFile(formData);
} catch (error) {
console.error('加载或合并 PDF 时出错:', error);
throw error;
}
};
// 将 Base64 数据转换为 File 对象
function base64ToFile(base64Data, filename) {
const arr = base64Data.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
}
export default pdfConvertImg;