【html转pdf】html页面导出为pdf文件,纯html版本,简单实现pdf转换【html2canvas+jspdf】

news/2024/7/24 5:21:07 标签: html, 前端, html转pdf, html2canvas, jspdf

前言

最近遇到的需求,把html转成pdf文件下载导出。
目前网上看了下,有三种方法,但是其中两种需要后端配合
一种是纯前端实现的,比较简单。所以就使用了这种。
也就是html2canvas + jspdf 的这种方法
这种方法实现的思路就是,通过html2canvas 把元素内的数据截图出来成一个图片
然后把这个图片通过jspdf 方法转成pdf格式输出出来
但是也有缺点,就是只是一个图片,而且清晰度也没有那么高。
只能说勉强实现一个需求,先应付一下,后续会继续看其他的写法,然后更新

效果图

这里是导出来后的效果,pdf格式的。只有一页
在这里插入图片描述
这里是网页上的,这个报告都是我排班出来的,图片和数据都是网上随便复制的,点击导出后会生成一个pdf文件。右边一大串的是base64格式的图片地址。也就是截图。
在这里插入图片描述

代码

这是html版本的,然后引入了vue的框架。
这里核心的是要引入html2canvas.js和jspdf.debug.js
资源的话我上传了,可以点击我的资源去下载,我设置了0积分下载,应该是可以直接下载
如果你们用的是纯vue版本,那就简单了。直接npm 下载这两个插件就行。

第一个.将页面html转换成图片 npm install --save html2canvas
第二个.将图片生成pdf npm install jspdf --save

<!DOCTYPE html>
<html>

<head>
  <meta charset='UTF-8'>
  <!-- 先引入 Vue -->
  <script src='vue.js'></script>
  <!-- 引入element-UI组件 -->
  <script src='element.js'></script>
  <link rel='stylesheet' href='element-index.css'>
  <!-- 引入axios -->
  <script src='axios.min.js'></script>

  <!-- 引入html2canvas 和 jspdf.debug-->
  <script src='./node_modules/html2pdf/js/html2canvas.js'></script>
  <script src='./node_modules/html2pdf/js/jspdf.debug.js'></script>
  
</head>

<body>
  <div id="app">
    <div class="layout">
      <div><button @click="downBtn" style="width: 70px; height: 30px" id="download-paper">pdf导出</button></div>
      <div ref="html2canvas" id="html2canvas">
        <div class="title">
          <div class="title_img">
            <img src="https://img2.baidu.com/it/u=384718229,1745978279&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=461" alt="" style="width: 70px;"  crossorigin="anonymous">
          </div>
          <div class="title_text">
            <p class="yiyuan">第一人民医院</p>
            <p style="font-size: 18px;font-weight:bold">消化内镜检查及手术记录报告</p>
          </div>
        </div>
        <div class="info1">
          <div class="info1left">检查号:12-10266</div>
          <div class="info1right">仪器型号:12-10266</div>
        </div>
        <div class="info2">
          <div class="info2top">
            <div>姓名:王小天</div>
            <div>性别:男</div>
            <div>年龄:34</div>
            <div>科别:内科</div>
            <div>申请医师:黄小燕</div>
          </div>
          <div class="info2bottom">
            <div>病历号:12312313546546464</div>
            <div>住院号:y229397</div>
            <div>病区号:四病区</div>
            <div>床位号:409</div>
          </div>
        </div>
        <div class="info3">
          <div>检查图像:</div>
          <div>
            <img :src="item" alt="" class="changimg" v-for="item,index in img2" :key="index"  crossorigin="anonymous">
          </div>
        </div>
        <div class="info4">
          <div style="font-weight: bold;margin-bottom: 5px;">内镜所见</div>
          <div style="font-size:14px;">食管:黏膜光滑柔软,血管纹理清晰,扩张度好,齿状线清晰。贲门:粘膜光滑,未见异常。 胃底:见一枚0.4*0. 4cm大小息肉,表面充血,予以摘除送检,粘液湖黄色,大量。胃
            :粘膜色泽潮红,下部窦体交界后壁见粘膜凹陷不平,片状发红,子以活检。胃角:后壁见片状发红糜烂灶,予以活检。胃窦: 胃窦后壁见大片状食管:黏膜光滑柔软,血管纹理清晰,扩张度好,齿状线清晰。贲
            :粘膜光滑,未见异常。 胃底:见一枚0.4*0. 4cm大小息肉,表
            面充血,予以摘除送检,粘液湖黄色,大量。胃 体:粘膜色泽潮
            红,下部窦体交界后壁见粘膜凹陷不平,片状发红,子以活检。胃
            :后壁见片状发红糜烂灶,予以活检。胃窦: 胃窦后壁见大片状
            发红病灶,表面不平,部分隆起、部分凹陷,染色表面结构紊乱,予以
            活检。幽门: 呈圆形,开闭尚可,粘膜色泽淡红,未见出血及渍
            疡。十二指肠: 球部及降部未见异常。活检。幽门: 呈圆形,开闭尚可,粘膜色泽淡红,未见出血及渍疡。十二指肠: 球部及降部未见异常。
          </div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">镜下诊断</div>
          <div style="font-size:14px;">
            1,胃多发病灶性质待定
            2,胃底息肉镜下摘除
            3,胆汁反流性胃炎
          </div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">病理号:</div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">活检部位:胃底、窦体交界后壁、胃窦后壁、</div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">病理诊断:</div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">医生建议:</div>
        </div>
        <div class="info5">
          <div>南京索图科技有限公司</div>
          <div>手术及诊断医师:王晓</div>
          <div>助手:</div>
          <div>检查日期:2022/8/27</div>
        </div>
        <div style="text-align:center;font-weight: bold;font-size: 14px;">仅供临床参考,不做证明材料!</div>
      </div>

    </div>
  </div>
</body>
<script>
  new Vue({
    el: '#app',
    data() {
      return {
        img2: [
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
        ]
      };
    },
    mounted() {

    },
    methods: {
      downBtn() {
        let dom = document.getElementById("html2canvas");
        //调用方法下载
        html2canvas(dom, {
          useCORS: true, //允许跨域
          allowTaint: false,
          logging: false,
          letterRendering: true,
          ddpi: window.devicePixelRatio * 4, //将分辨率提高到特定的DPI 提高四倍
          scale: 4, //按比例增加分辨率
          background: '#fff'//pdf背景色为白色,默认是黑色的
        }).then((canvas) => {
          //返回图片dataURL,参数:图片格式和清晰度(0-1)
          var pageData = canvas.toDataURL('image/jpeg', 1.0);

          //方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
          var pdf = new jsPDF('', 'pt', 'a4');

          //addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
          pdf.addImage(pageData, 'JPEG', 0, 0, 595.28, 592.28 / canvas.width * canvas.height);

          //保存到pdf,名字是stone
          pdf.save('stone.pdf');

        });
      },

    },
  })
</script>
<style>
  #html2canvas {
    width: 800px;
    height: 1280px;
    padding: 20px;
  }

  .title {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100px;
  }
  .title_text {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .yiyuan {
    font-size: 20px;
    font-weight: bold;
    color: blue;
  }

  .info1 {
    height: 30px;
    display: flex;
    justify-content: space-between;
    border-bottom: 1px solid #222;
  }

  .info2 {
    height: 100px;
    border-bottom: 1px solid #222;
  }

  .info3 {
    border-bottom: 1px solid #222;
  }
  .info4{
    border-bottom: 1px solid #222;
  }
  .info5{
    display: flex;
    justify-content: space-around;
    align-items: center;
    height: 50px;
  }
  .info2top {
    display: flex;
    justify-content: space-around;
    align-items: center;
    height: 40px;
  }

  .info2bottom {
    display: flex;
    justify-content: space-around;
    align-items: center;
    height: 40px;
  }

  .changimg {
    width: 180px;
    margin-right: 15px;
  }
</style>

</html>

细节事项

1,模糊问题通过html2canvas方法内的ddpi和scale放大控制清晰度
2,你下载的时候,导出按钮要放在上面,不能放在最下面,因为可能会由于你页面长了有滚动条,当你滚动到下面点击按钮的时候,上面滚动条看不到的部分是不会被截图的,也就是截图不全。但是如果你把按钮放在顶部,那就可以截全,哪怕下面的滚动部分看不到也可以截全,不知道是为啥。反正这个坑我是踩了,提醒你们一下。
3,这里是简单版本,所以没有分页功能,如果需要分页功能可以去网上找一下,pdf.addPage();这个方法就是添加新的分页,可以通过判断是否后面还有内容来触发这个方法,网上到处都是可以直接复制使用
这里给你们随便复制一个人的代码做参考

getPdf(title,url) {
        html2Canvas(document.querySelector('#pdfDom'), {
            allowTaint: false,
            taintTest: false,
            logging: false,
            useCORS: true,
            dpi: window.devicePixelRatio*4, //将分辨率提高到特定的DPI 提高四倍
            scale:4 //按比例增加分辨率
        }).then(canvas=>{
            var pdf = new jsPDF('p', 'mm', 'a4');    //A4纸,纵向
            var ctx = canvas.getContext('2d'),
                a4w = 190, a4h = 277,    //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
                imgHeight = Math.floor(a4h * canvas.width / a4w),    //按A4显示比例换算一页图像的像素高度
                renderedHeight = 0;
 
            while(renderedHeight < canvas.height) {
                var page = document.createElement("canvas");
                page.width = canvas.width;
                page.height = Math.min(imgHeight, canvas.height - renderedHeight);//可能内容不足一页
 
                //用getImageData剪裁指定区域,并画到前面创建的canvas对象中
                page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0);
                pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width));    //添加图像到页面,保留10mm边距
                
                renderedHeight += imgHeight;
                if(renderedHeight < canvas.height) {
                    pdf.addPage();//如果后面还有内容,添加一个空页
                }
                // delete page;
            }
            //保存文件
            pdf.save(title + '.pdf')
        })
    }

————————————————
版权声明:本文为CSDN博主「inticaler」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MICHAEL_PRINCE/article/details/118667848

4,注意这里页面的图片都是需要添加 crossorigin=“anonymous” 这句话的,这句话的意思是图片允许跨域,不然会出现图片空白的情况。
5,图片的地址如果你要测试,他只能接受http的那种或者base64格式的。不可以本地引入,像 . /xxx/xxx/xxx.png这种的路径是会报错的,我这里用的测试图片都是网络上的地址。


http://www.niftyadmin.cn/n/490459.html

相关文章

windows10强制删除文件_可能是最后一次机会,2 种方法免费升级到 Windows 10

根据微软公布的信息&#xff0c;十年前发布的 Windows 7 将于 2020年 1月14 日正式结束「扩展支持」&#xff0c;而与之相对的「主流支持」也在 2015 年 1 月 13 日就已经结束。相比此前 Windows XP 的生命周期&#xff0c;Windows 7 的生命周期并未获得延长&#xff0c;毕竟其…

苹果手机自带表格软件_手机系统自带软件不用却卸载不了,如何才能解决这个问题?...

手机系统自带软件不用却卸载不了&#xff0c;如何才能解决这个问题&#xff1f;很多人对于安卓手机中自带的软件非常头疼&#xff0c;因为很多预装软件你用不上&#xff0c;又不能卸载&#xff0c;它们还会自动联网&#xff0c;会在你不知道的情况下&#xff0c;耗费流量&#…

lateX 编译中文_【小白向】LaTeX 中文入门

注&#xff1a;本文尚未撰写完毕&#xff0c;先暂存一下~(2020/06/27)参考学习路线[1]如何从零开始&#xff0c;入门 LaTeX&#xff1f; 孟晨 1. 卸载 CTeX 套装&#xff0c;安装 TeX Live原因及教程见&#xff1a;TeX Live 下载及安装说明2. 看完&#xff1a;一份其实很短的 L…

大数据杀熟 算法_大数据杀熟这事,究竟有多没谱?

同一时间&#xff0c;打开不同手机查看同一航班机票&#xff0c;价格为何相差近千元?在线旅游平台背后的“大数据杀熟”近年来逐渐为人熟知。9月中旬&#xff0c;央视新闻在微博上发起投票“你遭遇过大数据杀熟吗”&#xff0c;勾选“遇到过&#xff0c;价格差异明显”的用户有…

博图注册表删除方法_回收站被清空文件删除的恢复方法

前几天一个同事不小心删除了回收站里的文件&#xff0c;但是想起来还有用&#xff0c;但是怎么也找不回来了&#xff0c;着急半天&#xff0c;最后我给他恢复回来&#xff0c;高兴坏了。今天就来说说回收站文件删除后恢复的方法。很多人在碰到不需要的文件时都是选择删除掉&…

人脸反光识别和读数识别_树莓派人脸识别实际应用:人脸识别门禁

2020-3-16 之前舵机开门关门逻辑有点混乱&#xff0c;不合乎常理&#xff0c;现对树莓派人脸识别代码进行修改&#xff0c;以及Arduino控制代码有所调整&#xff1b;在上一篇文章树莓派调用百度人脸识别API实现人脸识别&#xff0c;我们完成了树莓派人脸识别的基础环境配置&…

信捷plc485通信上位机_STM32L476R快速入门——串口与上位机通信

串口通信由两种方式&#xff0c;第一种就是用微机原理课上学过的TX和RX两个接口进行通信。不过根据去年的经验&#xff0c;这个板子直接用TX和RX两个接口进行通信容易被烧坏&#xff0c;所以我们就用更简单的usb通信。在发stm32的时候&#xff0c;老师会给你一个usb的供电线&am…

ajax nginx 转发 sessionid_腾讯内部技术文档:Netty+Nginx+Redis实战笔记

Netty现代互联网架构&#xff0c;分布式系统是一个绕不开的话题。一款优秀的网络通信框架将在分布式系统的构建中起到举足轻重的作用。其中&#xff0c;特别出名的有 SUN 公司的 Grizzly 框架、JBoss 的 XIO、Apache 的 MINA 以及赫赫有名也是使用最广泛的 Netty 框架。需要指出…