【微信小程序开发】多图片转pdf(可带水印)

一、首先需要在小程序中安装两个模块,直接使用npm:

npm install pdf-lib;

npm install @pdf-lib/fontkit;

二、微信开发着工具左上角,点击:构建npm。

 到了这里基本上就完成一半了,下面直接上代码

在utils文件新建pdf.js文件,这个可以随意起名

文件代码:

    async function pdfFn(imgArr, isWatermark) {
        const {
            PDFDocument,
            rgb
        } = require('pdf-lib'); //引入pdf-lib模块,转成pdf的时候用到
        const {
            fontkit
        } = require('@pdf-lib/fontkit') //引入@pdf-lib/fontkit模块,水印的时候用到
        //接收小程序端传来的图片数组
        let img_arr = imgArr;
        //arr是用来存储fileContent的数组
        let arr = [];
        //pdf的总高度,是等于数组里面的所有图片的高度之和
        let zheight = 0;
        //用来存储处理过后的各个图片信息的数组
        let content_arr = [];

        const doc = await PDFDocument.create();
        let page = doc.addPage();
        doc.registerFontkit(fontkit);

        // 下载图片 获取fileContent,并且存入arr数组
        for (let i = 0; i < img_arr.length; i++) {
            let lian = img_arr[i]
            let sBase64 = wx.getFileSystemManager().readFileSync(lian, 'base64');
            arr.push(sBase64);
        };

        // //获取所有照片组成的高度和宽度
        for (let j = 0; j < arr.length; j++) {
            //判断图片是png
            if (img_arr[j].match(/.png/g)) {
                let img = await doc.embedPng(arr[j]);
                //计算图片展示的宽高,根据原有的比例和pdf的宽度来算
                let h = (img.height * 700) / img.width;
                let obj = {
                    img: img,
                    width: 700,
                    height: h,
                };
                content_arr.push(obj);
                zheight = parseInt(zheight + h);
            };
            //判断图片是jpg
            if (img_arr[j].match(/.jpg/g)) {
                let img = await doc.embedJpg(arr[j]);
                //计算图片展示的宽高,根据原有的比例和pdf的宽度来算
                let h = (img.height * 700) / img.width;
                let obj = {
                    img: img,
                    width: 700,
                    height: h,
                };
                content_arr.push(obj);
                zheight = parseInt(zheight + h);
            };
            //判断如果图片不是png或者jpg。则返回提示
            if (!img_arr[j].match(/.jpg/g) && !img_arr[j].match(/.png/g)) {
                let str = '图片只支持jpg和png格式'
                return str
            };
        };

        //开始设置pdf的高度和宽度
        page.setWidth(800);
        page.setHeight(zheight);

        //guodu_height用来存储排在前面的高度
        let guodu_height = 0;
        //开始绘制
        for (let i = 0; i < content_arr.length; i++) {
            guodu_height = guodu_height + content_arr[i].height
            let height = zheight - guodu_height
            page.drawImage(content_arr[i].img, {
                x: 50, //左右各间隔50
                y: height,
                width: content_arr[i].width,
                height: content_arr[i].height,
            });
        };
        // 嵌入水印,水印不能中文,不然会报错
        if (isWatermark==1) {
            page.moveTo(100, zheight / 2);
            page.drawText(`Identification Assistant \n` +
                `\n` +
                `version: 1.0.12 \n`, {
                    size: 50,
                    color: rgb(1, 0, 0),
                });
            page.moveDown(100);
            page.drawText('Exclusive Watermark', {
                size: 40,
                color: rgb(1, 0, 0),
            });
        };
        const docBase64 = await doc.saveAsBase64();
        return {
            docBase64,
        };
    }


    module.exports = {
        pdfFn
    }

在需要的地方引入,比如:

使用:

onIdentify() {
        var that = this;
        wx.chooseMedia({
            count: 9,
            mediaType: ['image'],
            sourceType: ['album', 'camera'],
            success: (res) => {
                const imagePath = res.tempFiles.map(res => {
                    return res.tempFilePath
                })
                pdfFn(imagePath,2).then((resl) => {
                    var fs = wx.getFileSystemManager();
                    fs.writeFile({
                        filePath: wx.env.USER_DATA_PATH + "/" + 'pdf名字.pdf',
                        data: resl.docBase64,
                        encoding: "base64",
                        success: resx => {
                            wx.openDocument({
                                filePath: wx.env.USER_DATA_PATH + "/" + 'pdf名字.pdf',
                                showMenu: true,
                                success: function (resxl) {
                                    console.log(resxl);
                                },
                                fail(err) {
                                    console.log(err);
                                }
                            })
                        }
                    })
                })
            }
        })
    },
这里需要使用wx.chooseMedia从本地或相机获取图片的临时文件路径,将文件路径传给pdfFn函数,pdfFn接受两个参数,一个是图片的临时文件路径(数组),一个的是否追加水印(1为追加,其他不追加);具体可以自行去改pdf.js文件,都写了注释,很好理解。其他一些基础的的就不一一讲解了,有不懂的可以问我。
### 如何在 UniApp 微信小程序中实现 PDF 文件预览 为了实现在 UniApp 中的微信小程序里预览 PDF 文件的功能,可以采用 `web-view` 组件加载在线 PDF 查看器的方式。这种方式能够很好地适配不同类型的设备并提供较为流畅的用户体验。 对于直接通过 URL 访问 PDF 文件的情况,在 web-view 中可以直接指定该 URL 进行展示[^1]: ```html <template> <view> <!-- 使用 web-view 加载 pdf --> <web-view :src="pdfUrl"></web-view> </view> </template> <script> export default { data() { return { pdfUrl: 'https://example.com/path/to/your/document.pdf' // 替换成实际的PDF链接 }; } }; </script> ``` 然而当遇到经过代理服务器处理后的请求时(即URL不以`.pdf`结尾),可能会导致部分平台无法正常解析文档内容而出现白屏现象。针对这一情况,建议使用 PDF.js 来解决跨平台兼容性问题,并且还可以借此机会加入更多定制化特性比如添加水印等[^2]。 具体做法如下所示: #### 安装依赖库 首先需要引入 PDF.js 库到项目当中去。可以通过 npm 或者手动下载的形式完成安装操作。这里推荐利用 npm 方式来进行管理以便于后续维护升级工作更加便捷高效。 ```bash npm install pdfjs-dist --save ``` 接着确保已将字体资源也一并打包进来以免发生渲染异常状况: ```javascript import * as pdfjsLib from "pdfjs-dist"; // 导入worker脚本 import { Worker } from "pdfjs-dist/build/pdf.worker.entry"; pdfjsLib.GlobalWorkerOptions.workerSrc = Worker; ``` #### 编写页面逻辑 创建一个新的 Vue 页面用于呈现 PDF 文档视图。在此基础上编写相应的 JavaScript 方法来获取远程文件流数据并通过 canvas 元素绘制每一页的内容图像。 ```html <template> <scroll-view scroll-y class="container"> <canvas v-for="(page, index) in pages" :key="index" :id="'pdf-page-' + (index + 1)" style="width: 100%; height: auto;"></canvas> </scroll-view> </template> <script> import * as pdfjsLib from "pdfjs-dist"; import { getDocument } from "pdfjs-dist"; export default { onLoad(options) { this.loadPdf(options.url); }, methods: { async loadPdf(url) { const loadingTask = getDocument({ url }); const pdf = await loadingTask.promise; let totalPages = pdf.numPages; for (let pageNumber = 1; pageNumber <= totalPages; pageNumber++) { try { const page = await pdf.getPage(pageNumber); const viewport = page.getViewport({ scale: window.innerWidth / page.view[2] }); const canvasId = '#pdf-page-' + pageNumber; const query = uni.createSelectorQuery().in(this.$scope); query.select(canvasId).fields({ node: true, size: true }, res => { if (!res || !res.node) return; const canvas = res.node; const ctx = canvas.getContext('2d'); const renderContext = { canvasContext: ctx, viewport: viewport }; page.render(renderContext); }).exec(); } catch (error) { console.error(`Failed to fetch or render page ${pageNumber}`, error); } } this.pages = Array.from({ length: totalPages }, (_, i) => i + 1); } }, data() { return { pages: [] }; } } </script> <style scoped> .container { padding-top: 20rpx; } /* 添加一些样式调整 */ </style> ``` 上述代码实现了基本的 PDF 预览功能,同时也解决了由于路径格式引起的显示错误问题。如果还需要进一步增强应用的安全性和功能性,则可以在原有基础上继续扩展其他插件或服务端接口的支持。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值