生成pdf并下载

html2pdf.js

众所周知,H5生成pdf并下载最常用的就是html2pdf.js,而我也是众中的一位,常用的写法就是

scss 复制代码
downPdf(context) {
    htmlToPdf('#whiteBc', `${xxx}的报告`)
    function htmlToPdf(el,name) {
        let ele = document.querySelector(el);

        let opt = {
            margin: 20,
            filename:  name + '.pdf',
            pagebreak: { mode: ['avoid-all', 'css', 'legacy'] },
            image: {
                type: 'png',
                quality: 1
            },
            html2canvas: {
                scale: 2
            },
            jsPDF: {
                orientation: 'p',
                unit: 'pt',
                format: 'a4',
            }
        };

        html2pdf().set(opt).from(ele).save()
            .then(() => {
                
            })
            .catch(err => {
                console.error(err);
            })
    }
}

问题1:网络图片无法生成下载

解决1:直接把网络图片放在本地,引用本地的图片

问题是,我项目中的所有资源都是网络的,那把这些放到本地我不甘心啊

解决2:等待所有图片加载完成后再下载

javascript 复制代码
// 修改html2canvas的配置
html2canvas: {
    scale: 2,
    CORS: true,
    useCORS: true,  // 添加这个选项以支持跨域图片
    allowTaint: true,  // 允许加载跨域图片
}
const images = ele.querySelectorAll('img');
const imagePromises = Array.from(images).map(img => {
    return new Promise((resolve, reject) => {
        // 对于每一张图片,检查其 `complete` 属性是否为 `true`(即图片是否已经完全加载)
        if (img.complete) {
            resolve();
        } else {
            // 图片加载完成
            img.onload = resolve;
            // 如果图片加载失败也调用 `resolve()`,这意味着即使图片加载失败,整个Promise也不会被拒绝。
            img.onerror = resolve;
        }
    });
});
// 当所有图片加载完毕(成功或失败),再下载执行
Promise.all(imagePromises)
    .then(() => {
        return html2pdf().set(opt).from(ele).save();
    })
    .then(() => {
        
    })
    .catch(err => {
        console.error(err);
    })

这里有个问题:我发现到测试环境后不行了,图片跨域了,但是打开控制台就又行了,这也是我上测试环境的原因,因为开发时我的控制台一直被打开着。那到底为啥呢?没找到原因,恕我无能

解决3:把图片转成base64(稍微麻烦点,但是也算解决了)

javascript 复制代码
async handleImg(url) {
    return await this.toBase64(url)
},
toBase64(imgUrl) {
    return new Promise((resolve, reject) => {
        try {
            let image = new window.Image()
            image.setAttribute('crossOrigin', 'anonymous')
            image.src = imgUrl
            image.onload = () => {
                let canvas = document.createElement('canvas')
                canvas.width = image.width
                canvas.height = image.height
                let context = canvas.getContext('2d')
                context.drawImage(image, 0, 0, image.width, image.height)
                let quality = 0.8
                let dataurl = canvas.toDataURL('image/png', quality)
                resolve(dataurl)
            }
            image.onerror = (e) => {
                reject(e)
            }
        } catch (e) {
            reject(e)
        }
    })
}
csharp 复制代码
// 使用
await this.handleImg('https://rice-website.oss-cn-shanghai.aliyuncs.com/resource/a217e360-f520-4f13-9059-cdffa8f0af91.png')
// html2canvas可以把跨域的配置去掉了

问题2:当页面固定高度,内部滚动时,滚动到页面的下方再下载,下载的pdf上半部分会出现一片空白,并且下载的pdf页面也不完整

解决:下载的时候把页面滚到顶部(略显逊)

javascript 复制代码
window.scrollTo(0, 0)

再见。

相关推荐
人工智能训练3 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm
会跑的葫芦怪3 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
xiaoqi9224 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233224 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头88216 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas1366 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
摇滚侠6 小时前
2 小时快速入门 ES6 基础视频教程
前端·ecmascript·es6
2601_949833396 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter
珑墨7 小时前
【Turbo】使用介绍
前端
军军君017 小时前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three