有个新需求,当点击【下载】按钮时,直接将当前 html页面下载为 PDF。通过 html2canvas + jsPDF 可实现PDF单页下载,甚至是多页下载,记录分享一下~ 最后有源码,可自取

html2canvas

html2canvas官网在这:html2canvas - Screenshots with JavaScript

html2canvas 是一个 HTML 渲染器。该脚本允许你直接在用户浏览器截取页面或部分网页的“屏幕截屏”,通过读取 DOM 以及应用于元素的不同样式,将当前页面呈现为 canvas 图像

安装 html2canvas

npm install --save html2canvas

截取页面生成canvas,并将其插入页面中

html2canvas(document.body}).then(function(canvas) {
document.body.appendChild(canvas);
});

注意:受限于浏览器的实现,HTML 的 canvas 元素也有高度限制 可参考 canvas 最大画布尺寸 - MDN

  • Chrome 和 Firefox 等现代浏览器,canvas 的最大尺寸通常限制在 32767 像素,这也是 WebGL 和 2D canvas 的共同限制。超过这个值会导致 canvas 生成失败,抛出错误,或者显示空白内容。
  • 老版本的 IE 对 canvas 尺寸限制较为严格,一般在 8192 像素上下。现代版本的 Edge 则与 Chrome 的限制类似

jsPDF

jsPDF文档可以看这:GitHub - parallax/jsPDF: Client-side JavaScript PDF generation for everyone.

安装 jspdf

npm install jspdf --save

API也很简单,下面是个生成文本和图片的PDF样例

// jsPDF 下载文本图片PDF
const downLoadPdf = () => {
// 三个参数,第一个方向,第二个单位,第三个尺寸 'a4' = [595.28,841.89]
const doc = new jsPDF('', 'pt', [500, 1000]) // 字体大小
doc.setFontSize(50) // 文本,左边距,上边距
doc.text('Hello world!', 10, 50) // base64,图片类型,左边距,上边距,宽度,高度
doc.addImage(base64, 'PNG', 10, 60, 400, 200) doc.save('a4.pdf')
}

注意: jsPDF 生成的 PDF 默认以 pt (point) 为单位,单页的最大高度通常限制在 14400 pt。超过这个高度可能导致生成的 PDF 无法正确渲染或浏览器崩溃

html2canvas + jsPDF 实现页面下载

单页下载(自适应纸)

PDF页面的宽高 采用 canvas的宽高

  • canvas.height >= canvas.width,采用 portrait 纵向页面
  • canvas.width > canvas.height,采用 landscape 横向页面

如果页面很长的话,单页下载就会生成一张长长的PDF。注意!超过限制就会显示空白页面, jsPDF 生成的 PDF单页最大高度为 14400pt

canvas也有最大高度限制 32767像素,如果页面过长的话,通过 html2canvas 生成 canvas会失败

const downLoadPdfAutoSingle = () => {
html2canvas(document.body, {
scale: window.devicePixelRatio * 2, // 使用设备的像素比 * 2
}).then(canvas => {
// 返回图片dataURL,参数:图片格式和清晰度(0-1)
const pageData = canvas.toDataURL('image/jpeg', 1.0) const pageWidth = canvas.width
const pageHeight = canvas.height
const orientation = canvas.height >= canvas.width ? 'portrait' : 'landscape' // portrait 表示纵向,landscape表示横向
const pdf = new jsPDF(orientation, 'pt', [pageWidth, pageHeight]) // addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
pdf.addImage(
pageData,
'JPEG',
0,
0,
pageWidth,
pageHeight
)
pdf.save('下载一页PDF(自适应纸).pdf')
})
}

单页下载(A4纸)

已知:A4纸的宽度 和 canvas的宽度高度。可得 canvas在A4纸上占用的总高度(A4纸尺寸为宽 595.28pt,高 841.89pt)

如果页面很长的话,单页下载就会生成一张长长的PDF。注意!超过限制就会显示空白页面, jsPDF 生成的 PDF单页最大高度为 14400pt

canvas也有最大高度限制 32767像素,如果页面过长的话,通过 html2canvas 生成 canvas会失败

const downLoadPdfA4Single = () => {
html2canvas(document.body).then(canvas => {
// 返回图片dataURL,参数:图片格式和清晰度(0-1)
const pageData = canvas.toDataURL('image/jpeg', 1.0) // 方向纵向,尺寸ponits,纸张格式 a4 即 [595.28, 841.89]
const A4Width = 595.28
const A4Height = 841.89 // A4纸宽
const pageHeight = A4Height >= A4Width * canvas.height / canvas.width ? A4Height : A4Width * canvas.height / canvas.width
const pdf = new jsPDF('portrait', 'pt', [A4Width, pageHeight]) // addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
pdf.addImage(
pageData,
'JPEG',
0,
0,
A4Width,
A4Width * canvas.height / canvas.width,
)
pdf.save('下载一页PDF(A4纸).pdf')
})
}

多页下载(自适应纸)

由于 jsPDF 单页最大高度的限制 又或是 需求层面,我们需要实现自动分页下载

我们设置一页PDF页面宽度为canvas.width,高度为canvas.width * 1.3

分页思路:每个PDF页面都显示一张 canvas 图,只不过是计算偏移量,每个PDF页面显示的是 canvas 的不同位置

问题来了,如何创建一个新的PDF页面呢?可以使用 jsPDF 的pdf.addPage()

const downLoadPdfAutoMultiple = () => {
const ele = document.body
html2canvas(ele, {
scale: window.devicePixelRatio * 2, // 使用设备的像素比 * 2
}).then(canvas => {
let position = 0 //页面偏移
const autoWidth = canvas.width // 一页纸宽度
const autoHeight = canvas.width * 1.3 // 一页纸高度 // 一页PDF可显示的canvas高度
const pageHeight = (canvas.width * autoHeight) / autoWidth
// 未分配到PDF的canvas高度
let unallottedHeight = canvas.height // canvas对应的PDF宽高
const imgWidth = canvas.width
const imgHeight = canvas.height const pageData = canvas.toDataURL('image/jpeg', 1.0)
const pdf = new jsPDF('', 'pt', [autoWidth, autoHeight]) // 当canvas高度 未超过 一页PDF可显示的canvas高度,无需分页
if (unallottedHeight <= pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
pdf.save('下载多页PDF(自适应纸).pdf')
return
} while (unallottedHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
unallottedHeight -= pageHeight
position -= autoHeight
if (unallottedHeight > 0) {
pdf.addPage()
}
}
pdf.save('html2canvas+jsPDF下载PDF.pdf')
})
}

多页下载(A4纸)

由于 jsPDF 单页最大高度的限制 又或是 需求层面,我们需要实现自动分页下载

我们设置一页PDF页面的宽高为A4纸尺寸,即宽 595.28pt,高 841.89pt

分页思路:每个PDF页面都显示一张 canvas 图,只不过是计算偏移量,每个PDF页面显示的是 canvas 的不同位置

问题来了,如何创建一个新的PDF页面呢?可以使用 jsPDF 的pdf.addPage()

const downLoadPdfA4Multiple = () => {
const ele = document.body
html2canvas(ele, {
scale: 2, // 使用设备的像素比
}).then(canvas => {
let position = 0 //页面偏移
const A4Width = 595.28 // A4纸宽度
const A4Height = 841.89 // A4纸宽 // 一页PDF可显示的canvas高度
const pageHeight = (canvas.width * A4Height) / A4Width
// 未分配到PDF的canvas高度
let unallottedHeight = canvas.height // canvas对应的PDF宽高
const imgWidth = A4Width
const imgHeight = (A4Width * canvas.height) / canvas.width const pageData = canvas.toDataURL('image/jpeg', 1.0)
const pdf = new jsPDF('', 'pt', [A4Width, A4Height]) // 当canvas高度 未超过 一页PDF可显示的canvas高度,无需分页
if (unallottedHeight <= pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
pdf.save('下载多页PDF(A4纸).pdf')
return
} while (unallottedHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
unallottedHeight -= pageHeight
position -= A4Height
if (unallottedHeight > 0) {
pdf.addPage()
}
}
pdf.save('下载多页PDF(A4纸).pdf')
})
}

源码

GitHub - burc-li/vue-pdf: HTML 转 PDF下载(html2canvas 和 jsPDF实现)

前端实现 HTML 网页转 PDF 并导出🤓的更多相关文章

  1. 前端实现在线预览pdf、docx、xls、ppt等文件

    思路:前台将各种格式的附件上传到服务器----后台通过方法将这些格式的文件转化成图片,前台通过放映ppt的方式将其展示在页面上. 关键点:reveal.js 参考文章:https://www.awes ...

  2. 实践指南-网页生成PDF

    一.背景 开发工作中,需要实现网页生成 PDF 的功能,生成的 PDF 需上传至服务端,将 PDF 地址作为参数请求外部接口,这个转换过程及转换后的 PDF 不需要在前端展示给用户. 二.技术选型 该 ...

  3. 使用Pechkin将HTML网页转换为PDF

    Pechkin开源组件使用wkhtmlbox,可以解析CSS样式,将网页转换为PDF文件, 支持URL,或者HTML字符串 1, 从NuGet程序管理器中获得Pechkin  GlobalConfig ...

  4. flying-saucer + iText + Freemarker实现pdf的导出, 支持中文、css以及图片

    前言 项目中有个需求,需要将合同内容导出成pdf.上网查阅到了 iText , iText 是一个生成PDF文档的开源Java库,能够动态的从XML或者数据库生成PDF,同时还可以对文档进行加密,权限 ...

  5. Python|网页转PDF,PDF转图片爬取校园课表~

    import pdfkit import requests from bs4 import BeautifulSoup from PIL import Image from pdf2image imp ...

  6. pypdf2:下载Americanlife网页生成pdf合并pdf并添加书签

    初步熟悉 安装 pip install pypdf2 合并并添加书签 #!/usr/bin/env python3.5 # -*- coding: utf-8 -*- # @Time : 2019/1 ...

  7. Java利用模板生成pdf并导出

    1.准备工作 (1)Adobe Acrobat pro软件:用来制作导出模板 (2)itext的jar包 2.开始制作pdf模板 (1)先用word做出模板界面 (2)文件另存为pdf格式文件 (3) ...

  8. python 爬虫,网页转PDF:OSError: No wkhtmltopdf executable found

    解决办法: 代码中设置参数: path_wk = r‘D:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe‘ #wkhtmltopdf安装位置 config ...

  9. 前端实现在线预览pdf、word、xls、ppt等文件

    最近在做一个公司的资源管理系统,一些知识小记一下. 1.前端实现pdf文件在线预览功能 方式一.pdf文件理论上可以在浏览器直接打开预览但是需要打开新页面.在仅仅是预览pdf文件且UI要求不高的情况下 ...

  10. Echarts导出为pdf echarts导出图表(包含背景)

    Echarts好像是只支持png和jpg的导出,不支持pdf导出.我就想着只能够将png在后台转为pdf了. 首先介绍一下jsp界面的代码. var thisChart = echarts.init( ...

随机推荐

  1. go高并发之路——本地缓存

    一.使用场景 试想一个场景,有一个配置服务系统,里面存储着各种各样的配置,比如直播间的直播信息.点赞.签到.红包.带货等等.这些配置信息有两个特点: 1.并发量可能会特别特别大,试想一下,一个几十万人 ...

  2. MySQL,你只需要看这一篇文章就够了!PART04--完结篇

    MySQL--DAY04 索引 定义 索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制. 一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引. 索引相当于一本书的目 ...

  3. games101_Homework3

    在Raster部分实现数值插值,然后实现四种不同的像素着色器 作业描述: 作业1:修改函数 rasterize_triangle(const Triangle& t) in rasterize ...

  4. Spring AI 再更新:如何借助全局参数实现智能数据库操作与个性化待办管理

    引言 好的,今天我们继续聊一下Spring AI的相关内容.在10月的时候,我使用Spring AI搭建了一个简易版的个人助理系统,整体来说效果还是非常不错的.通过这次尝试,我对业务系统与AI结合的探 ...

  5. 《Django 5 By Example》阅读笔记:p679-p765

    <Django 5 By Example>学习第10天,p679-p765总结,总计87页. 一.技术总结 1.channel 书里通过聊天软件功能演示Django中channel以及异步 ...

  6. 符合ASTM标准的雨流计数法及其不同的改进方法

    随着研究的深入,人们发现采用时间序列计算载荷谱太麻烦了,处理的工作量太大,我们不需要将每个时刻点的载荷都做运算,疲劳计算只需要提供幅值.均值和循环次数,鉴于此发展出了很多不同的计数方法,雨流法是最常见 ...

  7. PTA题目集4~6的总结性Blog

    · 前言 本次的三个作业,由答题判题程序- 4.家居强电电路模拟程序- 1.家居强电电路模拟程序 -2组成. 答题判题程序-4是对前三次判题程序的最后升级,设计多个子类继承于基础题类来实现对每种题型的 ...

  8. 查壳工具之Exeinfo PE

    简介 Exeinfo PE是一款免费.专业的程序查壳软件,可以查看exe.dll程序的编译信息,开发语言,是否加壳,壳的种类以及入口地址等信息. Exeinfo PE下载地址:https://gith ...

  9. rsync之实战

    简介 rsync是远程(或本地)复制和同步文件最常用的命令. 借助rsync命令,你可以跨目录,跨磁盘和跨网络远程与本地数据进行复制和同步.举例来说:在两台Linux主机之间进行数据备份和镜像.本文介 ...

  10. 用VuePress在GitHub Pages上搭建博客

    请先点击链接RobinDevNotes,体验用VuePress搭建博客的效果(logo还没有合适的替换),目前部署在GitHub Pages上,国内访问速度还可以,再阅读本文感受来龙去脉和搭建过程. ...