it编程 > 编程语言 > Javascript

纯前端生成PDF(jsPDF)并下载保存或上传到OSS的代码示例

32人参与 2025-02-14 Javascript

前言

在工作中遇到了一个需求,就是把前端页面生成pdf并保存在本地,因为前端网站可能会展示各种表格,图表信息内容并带有比较鲜艳的色彩样式,如果让后端生产的pdf的话样式可能和前端页面展示的有所差异,所以这个任务就落到了前端的身上。

技术涉及

代码实现

1、获取dom结点

首先需要获取需要打印的dom结点,这个时候获取的dom结点是带有样式的,就相当于页面中的内容

 const elehtml = document.queryselector('.zxksbody');

2、获取打印容器的属性

首先做个兼容判断,判断是否取到了dom结点信息,如果取到了dom结点就获取dom结点的内容,进行高度和宽度的赋值

 if (elehtml) {
    let elew = elehtml.offsetwidth; // 获得该容器的宽
    let eleh = elehtml.offsetheight; // 获得该容器的高
 }

3、生成pdf

这一步就是把获取到的dom结点,通过jspdf和html2canvas 生成为pdf

html2canvas(elehtml, {
        dpi: 300,
        width: elew,
        height: eleh,
        scale: 2, // 提高渲染质量
        usecors: true  //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
      }).then(async (canvas) => {
            const pdf = new jspdf('', 'pt', 'a4');
            const imgdata = canvas.todataurl('image/png', 1.0);
            //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
            const imgwidth = 555.28;
            //一页pdf显示html页面生成的canvas高度;
            const imgheight = 555.28 / canvas.width * canvas.height;
            // 计算分页
            const pageheight = 841.89;
            //未生成pdf的html页面高度
            let leftheight = imgheight;
            //页面偏移
            let position = 0;

            if (leftheight < pageheight) {
              //在pdf.addimage(pagedata, 'jpeg', 左,上,宽度,高度)设置在pdf中显示
              pdf.addimage(imgdata, 'png', 20, 20, imgwidth, imgheight);
            } else { // 分页
               while (leftheight > 0) {
                  pdf.addimage(imgdata, 'png', 20, position, imgwidth, imgheight);
                  leftheight -= pageheight;
                  position -= 841.89;
                  if (leftheight > 0) {
                      pdf.addpage();
                  }
               }
         });

4、保存本地或者上传oss

 保存本地

保存本地的话比较简单,直接调用pdf库自带的方法就可以保存到本地

pdf.save(`${state.xsmc}-${state.xsbh}.pdf`)

上传oss

上传的oss的话就比较复杂一点,首先就是需要配置oss的内容,然后把pdf转换为blob对象,最后就是调用oss的接口实现上传。

// 配置oss
const client = new oss({
  region: "******",
  bucket: 'bucketname',
  endpoint: 'endpoint',
  ststoken: 'securitytoken',
  accesskeyid: 'accesskeyid',
  accesskeysecret: 'accesskeysecret',
});


// 将 pdf 文件转换为 blob 对象
const pdfblob = pdf.output('blob');

// 调用oss上方实现上传
const fileres = await client.put(`${state.xsmc}-${state.xsbh}.pdf`, pdfblob);
console.log(fileres, '接收返回的oss信息');

5、注意事项

html2canvas(elehtml, {
  onclone: (documentclone) => {
    // 在克隆的文档上进行修改
    const partright2 = documentclone.queryselector('.partright2');
    const titlebars = documentclone.queryselectorall('.titlebar');

    if (partright2) {
      partright2.style.display = 'none'; // 隐藏内容
    }
    if (titlebars) {
      //修改样式属性
      titlebars.foreach(titlebar => {
        titlebar.style.margintop = '-8px';
        titlebar.style.marginbottom = '20px';
      });
    }
  },
  dpi: 300,
  width: elew,
  height: eleh,
  scale: 2, // 提高渲染质量
  usecors: true  //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
}).then(async (canvas) => {
        .......
    });
// 获取全部内容
const elehtml = document.queryselector('.zxksbody');

// 在生成canvas之前就把样式进行更改,获取盒子的正常高度或者宽度,防止样式被遮盖,
const changeheight = document.queryselector('.zxkscontent');

if (changeheight) {
  changeheight.style.height = '100%'; // 更改高度
}

html2canvas(elehtml, {
    dpi: 300,
    width: elew,
    height: eleh,
    scale: 2, // 提高渲染质量
    usecors: true  //允许canvas画布内 
 }).then(async (canvas) => {

        .....

        // 在打印完成后,再把样式改回去
        if (changeheight) {
           changeheight.style.height = 'calc(100vh - 182px)';
        }
    }

// 对于vue

可以使用v-if进行更换,把展示的内容保存在div中,去掉溢出滚动功能

// 对于react

可以使用三元运算符进行判断,展示的内容

6、完整代码

const printpdf = async () => {
       const client = new oss({
              const client = new oss({
              region: "******",
              bucket: 'bucketname',
              endpoint: 'endpoint',
              ststoken: 'securitytoken',
              accesskeyid: 'accesskeyid',
              accesskeysecret: 'accesskeysecret',
        }); 
       try {
          // 获取全部内容
          const elehtml = document.queryselector('.zxksbody');
          // 带有移除隐藏的功能
          const changeheight = document.queryselector('.zxkscontent');

          if (changeheight) {
            changeheight.style.height = '100%'; // 更改高度
          }

          if (elehtml) {
            let elew = elehtml.offsetwidth; // 获得该容器的宽
            let eleh = elehtml.offsetheight; // 获得该容器的高

            // 确保获取加载完全的dom
            settimeout(() => { 
              html2canvas(elehtml, {
                onclone: (documentclone) => {
                  // 在克隆的文档上进行修改
                  const partright2 = documentclone.queryselector('.partright2');
                  const titlebars = documentclone.queryselectorall('.titlebar');

                  if (partright2) {
                    partright2.style.display = 'none'; // 隐藏内容
                  }
                  if (titlebars) {
                    titlebars.foreach(titlebar => {
                      titlebar.style.margintop = '-8px';
                      titlebar.style.marginbottom = '20px';
                    });
                  }
                },
                dpi: 300,
                width: elew,
                height: eleh,
                scale: 2, // 提高渲染质量
                usecors: true  //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
              }).then(async (canvas) => {
                const pdf = new jspdf('', 'pt', 'a4');
                const imgdata = canvas.todataurl('image/png', 1.0);
                const imgwidth = 555.28;
                const imgheight = 555.28 / canvas.width * canvas.height;

                // 计算分页
                const pageheight = 841.89;
                let leftheight = imgheight;
                let position = 0;

                if (leftheight < pageheight) {
                  pdf.addimage(imgdata, 'png', 20, 20, imgwidth, imgheight);
                } else {
                  while (leftheight > 0) {
                    pdf.addimage(imgdata, 'png', 20, position, imgwidth, imgheight);
                    leftheight -= pageheight;
                    position -= 841.89;
                    if (leftheight > 0) {
                      pdf.addpage();
                    }
                  }
                }

                // 将 pdf 文件转换为 blob 对象
                const pdfblob = pdf.output('blob');
              
                // 使用 oss 客户端上传 blob 对象
                try {
                  const fileres = await client.put(`${state.xsmc}-${statexsbh}.pdf`, pdfblob);
                  console.log('client res', fileres);
                } catch (err) {
                  console.error('pdf上传失败,请重新提交!', err);
                }

                if (changeheight) {
                  changeheight.style.height = 'calc(100vh - 182px)';
                }
              });
            }, 1000);
          }
        } catch (error) {
          console.log("error!", error);
          if (changeheight) {
            changeheight.style.height = 'calc(100vh - 182px)';
          }
        }
      };

总结 

到此这篇关于纯前端生成pdf(jspdf)并下载保存或上传到oss的文章就介绍到这了,更多相关 前端生成pdf并下载保存或上传到oss内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

前端实现图片压缩方案总结(干货)

02-14

在webview中如何跳回小程序步骤详解

02-14

Next.js中处理时区的常用方案推荐

02-14

在前端中Proj4.js使用简单介绍及进阶应用

02-14

JavaScript中的6种变体函数的区别和应用

02-14

前端滚动锚点三个常用方案(点击后页面滚动到指定位置)

02-14

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论