搜索
简帛阁>技术文章>jsPDF将html页面生成pdf文件的前端解决方案及html2canvas如何真正解决跨域图片的问题

jsPDF将html页面生成pdf文件的前端解决方案及html2canvas如何真正解决跨域图片的问题

  jsPdf是一个可以把html转成pdf的插件,有人多人在用。

  但是老外做的很多东西没考虑过英文之外的语言,这个也不例外,不支持中文,而且页面还原度也不是很好。

  网上实例导出的是 A4 大小,用到的是 addImage,以及需要 html2canvas 库。其实就是把需要导出的网页,利用 html2canvas 生成图片,在 addImage 至 PDF 中。至于为什么需要先转成图片呢,直接网页转不是很好吗,还能文字复制。因为不支中文,而且,样式还原度也不高。当然,执意于文本复制,网上也有解决方式(搜索关键字:jsPDF 中文)。

  所以常用的解决方案就是:曲线救国: html2canvas + jsPdf

  既然你不支持中文,那我把页面转成图片,怕不怕,图片再导出PDF照样中!这种方式很常见、很省事,问题也很多图片拉伸、模糊,最重要这样导出的PDF是没有灵魂的,因为他里面的内容都是图片,不能复制。对于pdf操作要求比较高的,这种方案就不大适合。如果你喜欢这种可以参照这篇文章Javascript 将html转成pdf,下载,支持多页哦(html2canvas 和 jsPDF),写的很详细。

  采用这种方案也有一些问题需要处理,这里记录下,给后来人避坑。

1、html2canvas生成图片模糊的问题

  这个问题大多数都会遇到,可以看我之前的博客处理:html转为图片插件:html2canvas保存图片模糊问题解决

2、html2canvas偶尔生成大量空白漏掉一些元素问题

  在使用过程我发现有时候当滚动到底部时,生成的图片就会存在大量空白,漏掉很多元素

  解决方案就是在生成图片前滚动至顶部使生成图片的元素进入渲染区域内。添加如下代码即可:

document.documentElement.scrollTop = 0

3、html2canvas生成图片里包含跨域图片的处理

  这个问题也比较奇怪,在很多同版本浏览器上均可以生成跨域图片,但是在个别电脑上同版本浏览器也不行。会报跨域的错误,因为我们图片都是存储在阿里云的oss上

Access to image at 'https://......oss-cn-...aliyuncs.com/image/base/be6f..f.jpeg' 
from origin 'http://...:3001' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

  网上很多各种解决方案也不靠谱。所以最后还是自己看源码,在html2canvas官网:http://html2canvas.hertzen.com/,下载源码,这里先看一下之前写的博客,涉及到在线图片跨域转base64格式的问题:将在线图片转换成base64踩坑记录及静态资源跨域及缓存的处理

  通过之前这篇博客就可以看到问题,那么其实我们只要改下面2段代码即可

if (isInlineBase64Image(src) || useCORS) {
    // img.crossOrigin = 'anonymous';
    img.crossOrigin = '*';
}
// img.src = src;
img.src = src + '?v=' + Math.random();

  注释的为原代码,下面的为修改后的代码即可。

4、jsPdf分页问题

  页面过长,就涉及分页问题。因为 A4 是有固定页面大小的(宽:595.28, 高:841.89),保存的内容高度(缩放至A4宽度)超过该长度,则会出现截断问题。

  解决方式其实不多,分情况而定。其实最简单的方式是不分页。不是吗?不分页,啥问题都没。这个问题就是,为什么要分页?讲真,没有分页需求,也没有打印需求,没必要分页,不是吗?整个页面导成图片就行。

  不分页就是将元素宽高作为pdf文件的宽高就行

const pdf = new jsPDF('', 'pt', [contentWidth, contentHeight])

  如果确实要分页的话,如果是纯静态页面,还比较简单,根据 A4 的尺寸比例,预留好间隔,这样,裁剪的时候,便不会出现文本或者其他内容被裁成两半。

  如果是动态页面的话就比较复杂,前端实现方案就并不太合适了,建议采用后端实现方案。

5、实例代码

downPdf () {
  let _this = this
  document.documentElement.scrollTop = 0
  let canvas = document.createElement("canvas")
  let context = canvas.getContext("2d")
  let _articleHtml = document.getElementById('article-content')
  let _w = _articleHtml.clientWidth
  let _h = _articleHtml.clientHeight
  let scale = 3
  canvas.width = _w * scale
  canvas.height = _h * scale
  context.scale(scale, scale)
  let opts = {
    scale: 1,
    width: _w,
    height: _h,
    canvas: canvas,
    useCORS: true
  }
  html2canvas(_articleHtml, opts).then(canvas => {
    _this.createPdfAll(canvas, scale)
  })
},
createPdfAll (canvas, scale) {
  let contentWidth = canvas.width / scale
  let contentHeight = canvas.height / scale
  let pdf = new jsPDF('', 'pt', [contentWidth, contentHeight])
  let pageData = canvas.toDataURL('image/jpeg', 1.0)
  pdf.addImage(pageData, 'JPEG', -9, 0, contentWidth, contentHeight)
  pdf.save(`${this.detail.title}.pdf`)
},

  此种方案纯前端实现,无需后端配合,并且页面还原度比较高,对于pdf操作要求不高的需求,还是比较合适的解决方案。

  缺点就是无法复制,对pdf操作不大兼容,对于分页也不大友好,容易出现分割。其实后端实现方案也有蛮多,并且对于分页更友好,可以分情况选择不同方案。

jsPdf是一个可以把html转成pdf插件,有人多人在用。GitHub:https://githubcom/MrRio/jsPDF官方文档:http://rawgithackcom/MrRio/
html页面pdf下载两个js文件可供使用,地址如下:https://githubcom/linwalker/renderhtmltopdf唯一缺点是图片页不好解决,最终pdf文件如下:解决
结合html2canvasjsPDF实现html页面转pdfBy:授客QQ:103355122实践环境win10Vue296axios0180html2canvas100rc3jspdf153安装h
spdfjs+html2canvasHTMl导出PDF功能:PDF分页插入页头页尾输出A4格式PDF支持单页、多页输出效果预览:查看演示PDFdemo地址:demo需要引入JS文件:<sc
、需求来源:把可视化展示HTML页面打印成PDF文件报表二、html2canvas+jsPDF导出pdf原理:通过html2canvas遍历页面元素,并渲染生成canvas,然后canvas图片
录A4尺寸安装插件html2canvasjspdf在项目中引入遇到问题多行省略号图片Tainedcanvasesmaynotbeexportedbase64DataURLscheme支持
html2canvas是一个相当不错JavaScript类库,它使用了html5和css3一些新功能特性,实现了在客户端对网页进行截图功能。html2canvas通过获取页面DOM和元素样式
<buttononclickHtmlToPdf()>转储pdf</button><buttononclickHtmlToImage()>转储image</b
利用JavaScript页面截图生成图片传给后台插件:html2canvas一、总结一句话总结:10<scripttypetext/javascript>11functiontakeS
近在项目中遇到一个需求,需要提供网页截图功能。百度下发现html2canvas很好用。那就试试吧。资源下载地址插件下载地址:html2canvas下载地址使用方式项目使用react组件开发方式。