本帖最后由 鄂尔多斯 于 2024-10-31 11:53 编辑
大家好,想必都会遇到各种奇葩的要求,多数可以在平台上找的插件解决,但是也会有没办法满足要求的时候,
这时候就只能自己动手开发插件了;
近期我做了一款 受控文件PDF预览 的插件:
功能:预览pdf,通过数据库绑定的值生成预览效果
主要SQL获取的值:签名1,签名2,受控水印,文件地址;(这些值都是图片地址,预览效果如下)
基于pdf.js 开源项目:GitHub - mozilla/pdf.js: PDF Reader in JavaScript
目前来说能功能已经完善好了,效果也达到了
!!!但是问题不出现在这里
正常的PDF是有WORD转码而来的,公司却偏偏是打印机扫描出来的PDF文件,生成的预览效果如下:
然后发现天塌了,绘制的方向识别到成这样,而且暂时没有解决方案
原因可能是 扫描件的PDF为纯图片的模式,导致识别转码的时候,方向错误;
解决方案:取消掉扫描件,全部换成转码的
主要绘制代码如下:感谢个位的宝贵建议
async function modifyPdf() {
const url = FILE_URL;
const fontUrl = 'DENG.TTF'; // 字体路径需要定义
const sig_set = sin_img_set;
const watermarkImageUrl1 = sin_img_url1; // 水印图片路径
const watermarkImageUrl2 = sin_img_url2; // 水印图片路径
const watermarkImageUrl3 = sin_img_url3; // 水印图片路径
const watermarkImageUrl_ui = ui_img_url1; // 水印图片路径
// 请求地址并变成arrayBuffer
const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer());
// 请求地址并把字体文件变成arrayBuffer
const fontBuffer = await fetch(fontUrl).then(res => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes);
pdfDoc.registerFontkit(fontkit);
const customFont = await pdfDoc.embedFont(fontBuffer);
const pages = pdfDoc.getPages();
// 加载水印图片
async function fetchImage(url) {
if (!url) {
//console.warn('水印图片地址为空,使用替代图片。');
return null; // 返回 null 表示未加载
}
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`无法加载图片,状态码: ${response.status}`);
}
const arrayBuffer = await response.arrayBuffer();
const header = new Uint8Array(arrayBuffer).subarray(0, 4);
const isPng = header[0] === 0x89 && header[1] === 0x50 && header[2] === 0x4e && header[3] === 0x47; // PNG文件头检查
if (!isPng) {
throw new Error('输入的文件不是PNG格式');
}
return arrayBuffer;
} catch (error) {
console.error('加载图片时出错:', error);
return null; // 出错时返回 null
}
}
// 加载并嵌入水印图片
const watermarkImageBytes1 = await fetchImage(watermarkImageUrl1) || await fetchImage('null.png');
const watermarkImage1 = watermarkImageBytes1 ? await pdfDoc.embedPng(watermarkImageBytes1) : null;
const watermarkImageBytes2 = await fetchImage(watermarkImageUrl2) || await fetchImage('null.png');
const watermarkImage2 = watermarkImageBytes2 ? await pdfDoc.embedPng(watermarkImageBytes2) : null;
const watermarkImageBytes3 = await fetchImage(watermarkImageUrl3) || await fetchImage('null.png');
const watermarkImage3 = watermarkImageBytes3 ? await pdfDoc.embedPng(watermarkImageBytes3) : null;
const watermarkImageBytes_ui = await fetchImage(watermarkImageUrl_ui) || await fetchImage('null.png');
const watermarkImage_ui = watermarkImageBytes_ui ? await pdfDoc.embedPng(watermarkImageBytes_ui) : null;
// 获取每一页的宽高并设置最大宽度
const { width, height } = pages[0].getSize();
const maxWidth = width * 0.13; // 最大宽度为总宽度的 13%
// 获取水印图片的原始宽高
const { width: originalWidth, height: originalHeight } = watermarkImage1 ? watermarkImage1.scale(1) : { width: 0, height: 0 };
// 计算缩放因子
const scaleFactor = originalWidth > maxWidth ? maxWidth / originalWidth : 1;
// 计算自适应高度
const adaptiveHeight = originalHeight * scaleFactor;
// 设置水印图片的绘制参数绘制位置
const draw_x1 = width * sin_img_draw_x1;
const draw_x2 = width * sin_img_draw_x2;
const draw_x3 = width * sin_img_draw_x3;
const draw_y = height * (1 - sin_img_draw_y);
const draw_x = width * ui_img_draw_x;
const draw_y2 = height * (1 - ui_img_draw_y);
// 定义绘制水印图片的函数
function ItemDrawImage(wrl, x, y, w, h, o) {
return function(item) {
if (wrl) {
item.drawImage(wrl, {
x,
y,
width: w,
height: h,
opacity: o,
});
} else {
console.warn("水印图片无效,未绘制此图片。");
}
};
}
// 遍历每一页的数据给每一页都添加水印
pages.forEach((item, index) => {
// 仅在第一页绘制水印图片
if (index === 0 && sig_set === true) {
ItemDrawImage(watermarkImage1, draw_x1, draw_y, originalWidth * scaleFactor, adaptiveHeight, 1)(item);
ItemDrawImage(watermarkImage2, draw_x2, draw_y, originalWidth * scaleFactor, adaptiveHeight, 1)(item);
ItemDrawImage(watermarkImage3, draw_x3, draw_y, originalWidth * scaleFactor, adaptiveHeight, 1)(item);
}
// 在每一页重复绘制水印图片(如需)
ItemDrawImage(watermarkImage_ui, draw_x, draw_y2, width * 0.18, height * 0.09, 0.6)(item);
});
// 已经处理好的数据
const pdfBuffer = await pdfDoc.save();
return pdfBuffer;
}
|
|