JS实现PDF合并功能

最近接到一个需求,要实现将PDF合并并且实现静默打印功能。网上各种各样的方案,有后端合并、有用lodop的,不是要增加后端工作量,就是要客户端装插件,还有用pdf.js、jspdf、html2canvas的,不是不满足自己的功能需求,就是写的不全,能不能来点有用的或者简单点完整的,我就只是想要做pdf合并,然后可打印可下载,网上资料很多,好处是东西多,坏处是可能被带坑里去,所以想将我的方案,或者说我解决问题的方法记录下来,方法只是现有技术的灵活运用。

想到pdf.js可以将pdf分解成一张一张图片,那将多个pdf都分解成图片,再将图片拼接起来不就可以了吗?答案是肯定的,我们可以用pdf.js将图片分解。然后要怎么合并呢?jspdf可以将图片生成pdf,那咱们就只需要用到pdf.js和jspdf就能够合并pdf不是吗?不明白为什么pdf.js既然能够将pdf分解成图片,那为什么不能够直接将pdf合并,省去我们来合并的这一步呢?这个功能不是很正常的需求吗?有知道的小伙伴可以留言告知。

本次分享是一次曲线救国,下载完合并后的PDF文档自行打开,设置打印参数(还是有必要弹设置窗口,如果一定要静默打印,还是需要使用到lodop,静默需要收费,否则页脚有试用版水印,本次分享并不涉及)。

那现在我们来对这个功能进行分解吧,稍微懂点js的基本上都懂,这不就是分享这个功能的意义所在了吗?下面我们正式开始吧。

1、引用所需JS

    <script src="~/js/pdfjs/pdf.js"></script>
    <script src="~/js/pdfjs/jspdf.debug.js"></script>

2、根据项目实际功能,去加载pdf,选中加载、全选加载等等,就细说了,这些不是本次分享重点

//注意:Canvas渲染出来之前,合并pdf为空白,因此需要监听canvas是否渲染完,完成之前不允许合并

///pdfUrl:pdf地址;
///id:只是为了将canvas做个标记(一个pdf分解成多张canvas图片,canvasid="id-页码"),区分不同pdf,后面可以根据id找到对应的pdf,
function loadPDF(pdfUrl, id) {
            pdfUrl && PDFJS.getDocument(pdfUrl).then(function (pdf) {
                //用 promise 获取页面
                var canvasid = '';
                var idTemplate = 'pdf_' + id + '-';
                var pageNum = pdf.numPages;
                pageNum_all += pageNum;
                //根据页码创建画布
                createSeriesCanvas(pageNum, idTemplate);
                //将pdf渲染到画布上去
                for (var i = 1; i <= pageNum; i++) {
                    canvasid = idTemplate + i;
                    renderPDF(pdf, i, canvasid);
                }
            });           
        }
        //创建和pdf页数等同的canvas数
        function createSeriesCanvas(num, template) {
            var id = '';
            for (var j = 1; j <= num; j++) {
                id = template + j;
                createPdfContainer(id, 'pdfClass');
            }
            // $("#container").append("<a href='javaScript:closePDF()' class='closeP'>点击收起</a>");
        }
        //创建
        function createPdfContainer(id, className) {
            var pdfContainer = document.getElementById('pop');
            var canvasNew = document.createElement('canvas');
            canvasNew.id = id;
            canvasNew.className = className;
            pdfContainer.appendChild(canvasNew);
        };
        //渲染pdf
        //建议给定pdf宽度
        function renderPDF(pdf, i, id) {
            pdf.getPage(i).then(function (page) {
                var scale = 1.5;
                var viewport = page.getViewport(scale);
                //
                //  准备用于渲染的 canvas 元素
                //
                var wrapper = document.getElementById("pop");
                var canvas = document.getElementById(id);
                var context = canvas.getContext('2d');
                canvas.height = viewport.height;
                canvas.width = viewport.width;
                canvas.style.width = "100%";
                canvas.style.height = "100%";
                wrapper.style.width = Math.floor(viewport.width / scale) + 'pt';
                wrapper.style.height = Math.floor(viewport.height / scale) + 'pt';
                //
                // 将 PDF 页面渲染到 canvas 上下文中
                //
                var renderContext = {
                    canvasContext: context,
                    viewport: viewport
                };
                //page.render(renderContext);
                // Step 1:store a refer to the renderer
                var pageRendering = page.render(renderContext);
                //步骤:钩入pdf渲染完成事件
                var completeCallback = pageRendering._internalRenderTask.callback;
                pageRendering._internalRenderTask.callback = function (error) {
                    //第二步:调用完成方法之前要做的事情
                    completeCallback.call(this, error);
                    //第3步:做一些更多的东西
                    pageNum_compelted++;
                    //注意:渲染完成之后需要做的事情,渲染出来之前,合并pdf为空白
                    if (pageNum_all == pageNum_compelted && pageNum_all != 0) {
                        $("#mulitprint").find("svg").hide();
                        $("#mulitprint").find("i").show();
                    } else {
                        $("#mulitprint").find("svg").show();
                        $("#mulitprint").find("i").hide();
                    }
                };
            });
        };

3、将pdf分解成canvas图片之后,就要将图片合并成一个pdf了

注意:

1>、canvas.toDataURL("image/JPEG");JPEG格式生成的pdf最小,png格式大非常非常多,此处划重点

2>、想要直接将pdf输出到iframe中,未能实现,data:application/pdf;base格式按理可以打开,在浏览器中也无法打开,知道的小伙伴留言告知,感谢!

3>、曲线救国,下载完自行打开,设置打印参数(还是有必要弹设置窗口,如果一定要静默打印,那本次分享并不满足)

 

function createPDF() {
            if ($("#pop>canvas").length <= 0) {
                Mozlite.alert("请选择打印文档!");
                return;
            }
            if (pageNum_all != pageNum_compelted || pageNum_all == 0) {
                Mozlite.alert("请等待文档合并完成!");
                return;
            }
            var doc = new jsPDF('', 'pt', 'a4');
            var pop = document.getElementById("pop");
            $("#pop>canvas").each((index, canvas) => {
                if (index > 0)
                    doc.addPage();//添加页
                //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
                var contentWidth = canvas.width;
                var contentHeight = canvas.height;
                var imgWidth = 595.28;
                var imgHeight = 592.28 / contentWidth * contentHeight;
                var canvas_1Url = canvas.toDataURL("image/JPEG");
                doc.addImage(canvas_1Url, 'JPEG', 0, 0, imgWidth, imgHeight);
            })
            var outputstr = doc.output('datauristring');
            console.log(outputstr);
            doc.save('待打印文件.pdf');
            //doc.output('datauri');
            //var outputstr = doc.output('datauristring');
            //console.log(outputstr);
            // document.getElementById("preview").src = outputstr;//在iframe中显示

            //var blob = doc.output('blob')//输出为blob
            console.log(blob);
            blob转url
            //var urll = window.URL.createObjectURL(new File([blob], 'a_name.pdf', { type: 'application/pdf' }))
            //console.log(urll);
            用PDFjs打开这个url能看到pdf 可以打印 /下载等
            viewer.html 时本地路径 具体看下面
            //window.open('/pdf/viewer.html?file=' + encodeURIComponent(urll))
            //document.getElementById("iframePrint").src = doc.output('datauristring');//在iframe中显示
        }

 

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Vue中合并PDF可以使用pdf-lib库来实现pdf-lib是一个纯JavaScript库,它可以用来创建、修改和提取PDF文档的内容。 首先需要安装pdf-lib库,可以使用npm命令进行安装: ``` npm install pdf-lib ``` 接下来,在Vue组件中引入pdf-lib库: ```javascript import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'; ``` 在合并PDF时,可以使用PDFDocument类创建一个新的PDF文档并添加多个PDF页面。假设我们有两个PDF文件,file1.pdf和file2.pdf,代码如下: ```javascript // 创建一个新的PDF文档 const mergedPdf = await PDFDocument.create(); // 读取第一个PDF文件 const file1 = await fetch('file1.pdf').then(res => res.arrayBuffer()); // 读取第二个PDF文件 const file2 = await fetch('file2.pdf').then(res => res.arrayBuffer()); // 将第一个PDF文件添加到新的PDF文档中 const pdfDoc1 = await PDFDocument.load(file1); const pages1 = await mergedPdf.copyPages(pdfDoc1, pdfDoc1.getPageIndices()); pages1.forEach((page) => { mergedPdf.addPage(page); }); // 将第二个PDF文件添加到新的PDF文档中 const pdfDoc2 = await PDFDocument.load(file2); const pages2 = await mergedPdf.copyPages(pdfDoc2, pdfDoc2.getPageIndices()); pages2.forEach((page) => { mergedPdf.addPage(page); }); // 将合并后的PDF文档输出为二进制数组 const mergedPdfFile = await mergedPdf.save(); ``` 以上代码将读取两个PDF文件,将它们添加到新的PDF文档中,并将合并后的PDF文档输出为二进制数组。 需要注意的是,pdf-lib在浏览器环境下可能会受到一些安全限制,需要在服务器端进行合并PDF

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值