实现步骤:(只想了解vue实现的不用看方法一,直接看二)

方法1:

使用node.js和puppeteer(谷歌自动检测工具),由于第一种尝试结果不太理想,所以我直接粗略讲解:(原代码实现如下,依赖包并非所有都有用,puppeteer是必需要npm按照并且引入)

const puppeteer = require('puppeteer');const useProxy = require('puppeteer-page-proxy');const {delay} = require("bluebird");const Promise = require("bluebird");const ms = require("ms");const fs = require('fs');(async () => {const browser = await puppeteer.launch();// const browser = await puppeteer.launch({headless:false});// const page = await browser.newPage();const page = await browser.newPage();await page.goto('http://127.0.0.1:5173/',{waitUntil:'networkidle2'});// await delay(ms("5s"));await page.pdf({path: './test123.pdf' , format: 'A4',printBackground:true});await browser.close();})();

实现原理很简单,就是通过puppeteer自动打开对于网页,然后调用他的pdf方法保存,值得注意的是这样printBackground:true这个参数控制的是背景颜色的显示,如果不选true,背景色是不会渲染出来的,这样做的好处是生成简单,图片非常清晰,即使放大后依旧清晰,并且不会有太大的内存,我这三张图片的原图就3m多,生成文件是3.56m可见比较符合预期的。缺点:①生成的pdf是默认两页,我尝试很多手段解决,可能是学术不精,我在puppeteer的API文档为找到对应的参数设置,百度搜索等方式也未找到好的解决方案,至今不清楚原因,我试了其他网站,有些一页就能显示完,具体原因我不详做叙述了,反正笔者可能是陷入死胡同,尝试很多无果后选择了vue去解决。②由于这样需要打开新的窗口,就比如会有跳转操作,虽然有无头模式,但是我未去尝试,因为已经被①劝退了。

方法2:

方法参考来源:

Vue页面生成PDF的方法_vue生成pdf_愤怒小绵羊的博客-CSDN博客

在vue的项目中,先安装需要用到的两个依赖分别是html2canvas和jspdf

①npm install --save html2canvas②npm install jspdf --save

①的作用是将我们需要转换成PDF的html页页面先转换成canvas(canvas是html的一个标签,在画图、特效甚至小游戏方面非常重要,了解可以去看相关系列知识,不详解)转换成canvas之后我们可以通过一系列参数去调整我们需要转换的pdf,这里是非常重要的点,因为在默认情况下,生成的canva是非常模糊的,待会细讲问题及解决

②的作用就是将canvas转换成的图片转换成需要的pdf并且导出,这里能做的事情不多,也相对较为简单

接下来讲的是具体实现步骤:(参考博主愤怒的小绵羊,非常感谢分享,可以先根据小绵羊的代码来做,由于我的代码场景和他不同,我的并不是一个示例代码。可能会存在无法执行,但是绵羊的是可以的 我试过了。)

<template><button @click="handleExport">导出</button><div ref="pdf" class="spec">需要转换成pdf的结构或者图片</div></template>

然后定义点击函数,并且拿到对应页面的pdf传递给downloadPDF函数,由于downloadPDF结构比价多,将其抽离出来pdf.js里面保存

const handleExport =()=>{console.log(proxy.$refs.pdf)downloadPDF(proxy.$refs.pdf)}

然后导入js,由于pdf.js内容较多就将其抽离了

import {downloadPDF} from "./pdf.js"pdf.js内容如下:import html2canvas from "html2canvas";import jsPDF from "jspdf";import compress from './compress.js';function base64ToFile(dataURL) {var arr = dataURL?.split?.(',')let mime = arr[0].match(/:(.*?);/)[1]let bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}let filename = new Date().getTime() + "" + Math.ceil(Math.random() * 100) + "." + mime.split("/")[1]return (new File([u8arr], filename, { type: mime }))}export const downloadPDF = page => {html2canvas(page,{allowTaint: true, //开启跨域useCORS: true,scale: 2,}).then(function(canvas) {canvas2PDF(canvas);});};const canvas2PDF = canvas => {let contentWidth = canvas.width*0.2;let contentHeight = canvas.height*0.2;let imgHeight = contentHeight;let imgWidth = contentWidth;let pdf = new jsPDF("p", "pt");let sharePicsharePic = canvas.toDataURL("image/jpeg", 1)let fileba = base64ToFile(sharePic)compress(fileba).then(res => {pdf.addImage(res.compressBase64,"JPEG",0,0,imgWidth,imgHeight);// console.log(pdf,999)pdf.save("导出.pdf");}).catch(err => {// error(err);});};

到这里就已经可以将对应的html代码转换成pdf了,接下来我将讲解我遇到的问题已经解决方案:

问题及解决:

①打印出的PDF没有图片部分

我遇到的第一个问题就是打印出的pdf没有图片,我试了在nodejs+puppeteer情况下是可以直接打印,我猜测可能是转换成pdf的方式不同,可能puppeteer类似于截图(猜测观点),而vue这种先转换成canvas的形式是需要下载图片资源的,所有下载资源就存在跨域问题,一开始我是想通过配置代理的方式实现(后续会详细讲解跨域问题以及配置代理方法,帮助自己复习总结并且发出来),不过结果并不是很顺利,也可能是我操作的问题,于是我通过搜索发现,可以将图片转换base64的格式就能避开跨域问题了,http://nomad-public.oss-cn-shanghai.aliyuncs.com/size_chart/34e4debd-a8ea-4730-acd2-8a58cc7c6b5d.jpg?time=1677729826618,我大致观察了一下好像就是加了个时间戳,然后在图片前加上了image.setAttribute("crossorigin", "anonymous");据说是解决跨域策略的方法,接下来我就把将图片转换成base64的方法贴出来:

const downloadImage = (imgsrc) => {//下载图片地址和图片名(下载部分代码已经被我删除了,这是上一个需求用到了,我在此基础魔改了一下)var image = new Image();// 解决跨域 Canvas 污染问题,image.setAttribute("crossorigin", "anonymous");image.onload = function () {var canvas = document.createElement("canvas");canvas.width = image.width;canvas.height = image.height;var context = canvas.getContext("2d");context.drawImage(image, 0, 0, image.width, image.height);var url = canvas.toDataURL("image/png"); //将图片格式转为base64// console.log(url,"base64")};image.src = imgsrc + '?time=' + Date.now();  //注意,这里是灵魂,否则依旧会产生跨域问题console.log(image.src,"image.src")return image.src}

这个函数的作用就是传入一个url,函数就会将转换base64格式的图片url返回了(可能概念会有错,因为我base64和canvas理解较浅),这样再去转换成pdf就会发现可以看到图片了,顺便小提一嘴,如果是背景图片的格式可以在template中用模板字符串以动态形式添加:style="{'margin-top':'0','background-image':`url(${downloadImage('https://nomad-public.oss-cn-shanghai.aliyuncs.com/size_chart/929c3c47-e0b6-4765-bda9-5fb8c1c05191.jpg')})`}",这样就可以避开设置动态css样式了,这样就解决了第一个问题,pdf中无法显示图片。

②生成的PDF清晰度太低

当我打印出PDF之后,我又发现了一个问题,就是我的PDF清晰度太低了,像马赛克一样,于是我又去查询问题解决,有两种解决方案,一个增加scale(其实我们在css里面经常看到就是加大比例一样),我尝试了一下,确实可以,但是同时带来的是图片变得很大很大,由于需求是在一个A4纸大小,增进scale:4后字体等等清晰度是高了很多,但是纸张只能够展示出四分之一不到的内容(生成PDF的左上角),这样整个PDF不能全部展示在A4中,显然不如这样做,于是我又查到了一个参数dpi,整个参数的描述非常符合我的预期,但是就是没用,我也不知道是什么问题,可能是版本,因为我查到有一个html2canvas的参数中压根没有这一个参数,总之这条路(最简单)走不通了,于是在带我的大佬的点拨下,有了一个新的思路,就是在html转换成canvas的时候设置scale:2将转换的canvas画板变大,然后在转换成图片后缩小图片的大小,达到增加清晰度(其实和dpi实现思路一样,更麻烦了,因为dpi参数失效了)

html2canvas(page,{allowTaint: true, //开启跨域useCORS: true,scale: 2,}).then(function(canvas) {canvas2PDF(canvas);});

然后在此代码片段,缩小图片的大小,这个方法俗称先放大再缩小,先放大canvas(画板),在将其转换成图片后缩小图片的大小以增加清晰,这个步骤就是可以通俗理解成,你在一个巨大的画板下先画出需要的画面,由于画板很大,即使画的不是很清晰,在绘画完成后,将图片缩小到一个A4纸大小,那么在同样面积内像素就增加了很大,因为从一个巨大的画板都压缩在一个小小A4纸张上了,像素自然就高了(这是我个人理解)

const canvas2PDF = canvas => {下面位置就是width*0.2let contentWidth = canvas.width*0.2;let contentHeight = canvas.height*0.2;let imgHeight = contentHeight;let imgWidth = contentWidth;

然后依旧发现清晰度偏低,然后又有了第二个思路,就html代码结构放大,比如原本放在600px的盒子里面,将盒子改成1200px,其实和前面思路一样,一个是增大画板以提升精度,现在这个就是在绘画时候花大一点,那么画板自热而然也会加大,也可以理解成html缩到原来600px的时候像素肯定也会加大,这两个思路在我看来很相似。好的目前生成的图片清晰度已经很高了,基本可以满足公司的需求了,接下来又有一个问题。

③生成的PDF文件过于庞大

由于之前使用的方法中,修改html代码css样式以加大清晰度,那么就会带来一个大小,原来的图片也被放大了,那么如果只是简单再去缩小,图片会非常大,我试过再没被处理的情况下,转换成jpeg的情况下生成pdf大小在13m左右,原图的大小才3m,可见问题之大,这样pdf在文件传输的过程会非常浪费资源,于是我就研究起来了压缩,首先我优化了代码结构,对文件大小改动很小,于是从图片着手,传入图片是20kb左右的时候生成的PDF都依旧有3.8m左右,于是在代码canvas.toDataURL("image/jpeg", 1)处我将参数1修改成0.92,1就是百分百还原图片,0.92就是牺牲清晰度换来文件大小,效果很显著,从3.8m降到了1m,很符合预期,但是我改动了图片清晰度,显然是拆东墙补西墙,我的领导也跟我说这个清晰度较低,希望维持清晰度的情况下尽可能讲到1m,在开始我的认知里面,是越清晰就越大,虽然我也在市面上见过压缩pdf的软件,但是免费情况下都是牺牲清晰度换来文件大小的降低,除了付费情况,所以我开始不知道怎么办,我又去请教带我的那个大佬,大佬直接跟我说,可以啊,随便像压到多小都可以,还不降低清晰度,于是我大佬给了一个.js压缩方法给我,我试了一下直接把3m的压缩到400kb,由于代码是大佬给我的,没经过允许前我就不公开展示了,我写的代码和参考文章代码都放上了,如果有类似需求可以私信我,我可以私发,感谢大佬的分享。方法大概是传入文件,然后将图片转换成base64,然后用canvas处理,然后经过一些我还没研究清楚的方法缩小,如果后续我在网上搜索到公开代码我会在文章中分享出来补充。

最终效果展示:

特别鸣谢:感谢好兄弟某可提出的宝贵意见,已经修改代码处为代码块,经验不足,还请见谅,还有啥不便阅读的欢迎指出

Vue 如何将网页转换成PDF实现步骤以及问题解决:相关推荐

  1. 在 Linux 中把一个网页转换成 PDF的技巧介绍

    你如何在 Linux 中把一个网页转换成 PDF?你可以选择使用每个 Linux 发行版上的网页浏览器(GUI),或者使用终端将网页变成 PDF 文件. 在这里,我将提到这两种方法来帮助你完成工作. ...

  2. 1604_linux环境下使用命令行把网页转换成pdf

    全部学习汇总: GreyZhang/toolbox: 常用的工具使用查询,非教程,仅作为自我参考! (github.com) 使用的工具很容易在彼此之间产生隔离性障碍,比如我最近使用的墨水屏阅读的最合 ...

  3. php 网页转换成pdf,PHP html 转换成PDF wkhtmltopdf HTML 转换成 PDF

    因为涉及到账单,并且要生成PDF并发送邮件,所以试用了好多转换PDF的都不成功,基本上都是格式错乱,唯一就是 wkhtmltopdf 满足 我的需求 安装环境 CENTOS 7.3 下载及安装 wge ...

  4. 用c语言怎样将swf转化为pdf,利用ABCpdf.NET将网页转换成PDF的方法小结

    中转方式: 大多数时候,都是使用WebBrowser空间,将网页截图,然后插入PDF文件,另外也可以将网页先保存为Word文件,然后再从Word转PDF. PDF虚拟打印机: 还有一种方式,就是使用虚 ...

  5. Win10 中将网页转换成pdf的简便方法

    注意:该方法不是将网页完整地保存下来,而是选取其中主要的文字信息. (1)打开要保存的网页 (2)按快捷键 Ctrl+P 打开打印界面 (3)选择打印机为 "Microsoft Print ...

  6. HTML转换成PDF 指定网页转换PDF(实际上是截取网页) pdf.js , dompdf , html2ps , wkhtmltopdf

    开发背景 在实际开发过程中,有一些特殊需要:需要把相关网页转换成PDF格式,作为资料留存 下面讲一下我所遇到的相关需求:证书的发放,在前期的需求调研的时候甲方提出一个需求,电子证书需要实时生成并且通过 ...

  7. 如何把html转换pdf,怎么把html转换成pdf

    1.怎么将html格式文件转成pdf 1这个方法是我认为最简单.高效的,只要安装了360浏览器.火狐浏览器或谷歌浏览器就可以轻松实现.下面笔者以360浏览器为例,我们只要在浏览器的右上角点击" ...

  8. 如何将网页打印成PDF文档?没看错,这个真可以!

    当我们在浏览器上看到某篇文章时,需要保存下来,大家都会用哪种方式呢? 一般的小伙伴都是复制内容,然后粘贴到Word里,为了美观,然后再重新排版.其实这种方法并不是不可,但是如果遇到有限制的文章.那么就 ...

  9. cad的dwg如何转换成pdf?

    cad的dwg如何转换成pdf?pdf文件相信对于每个使用的电脑的小伙伴来说并不陌生,因为pdf文件几乎每天在工作中都会使用到,由于pdf文件的稳定性成为目前最重要的电脑文件之一,并且pdf文件可以在 ...

最新文章

  1. 函数字节不对齐函数崩溃_Excel中统计字符数,不需要一个一个的数,len函数能轻松搞定...
  2. Hadoop详解(六):MapReduce计算框架详解
  3. 为已创建好的临时表添加字段列
  4. php strstartwith,PHP8新增的三个字符串函数 str_contains, str_starts_with, str_ends_with
  5. Sizzle系列之 选择元素
  6. document.body为null的问题
  7. 一篇来自前端同学对后端接口的吐槽
  8. [Java基础]ArrayList集合常用方法
  9. [jQuery原理] jQuery事件操作相关方法
  10. sqlserver2005使用convert转换成各种格式的日期
  11. 开发环境 测试环境 定义_如何快速搭建ES开发测试环境?
  12. 卓克-为什么没有动物比蓝鲸的体型大?
  13. RazorPage介绍(一)
  14. c语言图片输出,C语言输出图片?
  15. 谷歌浏览器网页打不开怎么办
  16. Win7安装VMware
  17. 计算机报刊杂志推荐,计算机优秀期刊推荐 | Journal of Cloud Computing
  18. 30个免费且很棒的公共数据源分享
  19. 一行代码生成数据分析报告—Pandas-profiling
  20. hana数据库连接oracle,HANA SQL参考及Oracle对照

热门文章

  1. Android高仿微信微博多图展示
  2. 使用赛孚耐数据保护解决方案在整个生命周期内确保信息安全连载三:云范例威胁为信息保护基础带来更大的威胁...
  3. ​如何翻译PDF文件?教大家两种翻译方法
  4. 数据库中的字符char、nchar、nvarchar、nchar
  5. pd.to_excel()中关于pd数据到excel中行列设置规则总结
  6. 计算机音响使用方法,教你如何正确使用多功能迷你音响
  7. iPhone SDK开发:改变UISWitch文本和颜色(当初好像我没明白,现在也没明白)
  8. 21python_面向对象封装案例
  9. HTML(学习笔记)
  10. LRU和LFU的缺点