鄂尔多斯 发表于 2024-10-31 11:51:51

插件开发交流:关于通过数据库的绘制的PDF预览

本帖最后由 鄂尔多斯 于 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;
            }
         



1525755450 发表于 2024-11-1 09:46:34

:hjyzw::hjyzw::hjyzw:

137294886 发表于 2024-11-1 12:47:04

页: [1]
查看完整版本: 插件开发交流:关于通过数据库的绘制的PDF预览