h5页面转PDF下载(包括pc端和移动端) 您所在的位置:网站首页 链接怎么转换成pdf格式文件手机 h5页面转PDF下载(包括pc端和移动端)

h5页面转PDF下载(包括pc端和移动端)

2024-07-18 05:27| 来源: 网络整理| 查看: 265

前情:需要在app内嵌的weixin项目将页面转成PDF并下载。

使用技术:html2canvas插件 + jspdf插件

实现思路:1)将h5页面用canvas画成图片

                  2)利用jspdf将图片插入pdf文件并下载

缺点:生成的pdf是由图片拼接而成的,不能实现复制

实现版本:

     第一版:将h5页面转成一张长图,再根据A4值的高度将长图截成多个页面

         缺点:使用起来不灵活。没办法在每个页面上插入页眉页脚

         实现代码:

         1)weixin项目的  pdftemplate.vue文件

       (由于是内嵌微信项目,所以在微信项目页面能操作dom)

....... import { downloadPdf } from '@/common/utils/insPdfUtil' //实现转换的页面 export default { ...... mounted(){ if (this.calData && this.calData.userInfo && this.calData.userInfo.name) { this.htmlTitle = this.calData.userInfo.name + '的计划书' } //this.$refs.refContent.$el:需要转化的页面内容 //this.htmlTitle:文件名 downloadPdf(this.$refs.refContent.$el, this.htmlTitle) } }

        2)insPdfUtil.js文件

import html2canvas from 'html2canvas' import JsPDF from 'jspdf' /** * 创建并下载pdf * @param {HTMLElement} targetDom dom元素 * @param {String} title pdf保存名字 * @param {function} callback 回调函数 */ const downloadPdf = (targetDom, title, callback) => { html2canvas(targetDom, { useCORS: true }).then(function(canvas) { const contentWidth = canvas.width const contentHeight = canvas.height const pageHeight = (contentWidth / 592.28) * 841.89 let leftHeight = contentHeight let position = 0 const imgWidth = 595.28 const imgHeight = (592.28 / contentWidth) * contentHeight const pageData = canvas.toDataURL('image/jpeg', 1.0) const PDF = new JsPDF('', 'pt', 'a4') if (leftHeight < pageHeight) { PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) } else { while (leftHeight > 0) { PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) leftHeight -= pageHeight position -= 841.89 if (leftHeight > 0) { PDF.addPage() //添加pdf页树 } } } PDF.save(title + '.pdf') //pdf下载 if (typeof callback === 'function') { callback() } }) } export { downloadPdf }

   第二版:在h5页面上先设置好每一页要显示的数据存为对象传给insPdfUtil页面遍历生成PDF

 缺点:移动设备部分下载失败

知识点:html2canvas插件可以绘制$el虚拟dom,也可直接传真实DOM(注:需要注册到页面上,可以在页面上定义一个div占位,在操作dom元素将元素插入该位置)

实现代码:

 1)weixin项目的   pdftemplate.vue文件

1、使用ref获取虚拟dom的方式 2、使用操作dom的方式 3、动态生成dom,必须要挂载到页面上,可以先在页面写一个占位的标签 ... ... ... ....... import { downloadPdf } from '@/common/utils/insPdfUtil' //实现转换的页面 export default { ...... //--定义为数组遍历 data(){ refList: [] } mounted(){ if (this.calData && this.calData.userInfo && this.calData.userInfo.name) { this.htmlTitle = this.calData.userInfo.name + '的计划书' } //this.$refs.refContent.$el:需要转化的页面内容 //this.htmlTitle:文件名 this.refList.push(this.$refs.refContent.$el) let topBody = document.queryselect('.topBody') this.refList.push(topBody) //--动态生成dom,必须要挂载到页面上,可以先在页面写一个占位的标签 let div = document.createElement("div") div.innerHtml = '动态生成的div' let perch = document.createElement("perch").appendChild(div) this.refList.push(div) downloadPdf(this.refList, this.htmlTitle, () => {回调函数}) } }

        2)insPdfUtil.js文件

import html2canvas from 'html2canvas' import JsPDF from 'jspdf' /** * 创建并下载pdf * html2canvas画是异步画图,所以这里需要用到promise.all * @param {HTMLElement} targetDom dom元素 * @param {String} title pdf保存名字 * @param {function} callback 回调函数 */ const downloadPdf = (targetList, title, callback) => { var pdf = new JsPDF('', 'pt', 'a4', true) const promiseList = [] targetList.forEach((item) => { promiseList.push( html2canvas(item, { useCORS: true, scale: 1 }) ) }) Promise.all(promiseList).then((resList) => { resList.forEach((item, index) => { var contentWidth = item.width var contentHeight = item.height // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 var imgWidth = 595.28 var imgHeight = (592.28 / contentWidth) * contentHeight var pageData = item.toDataURL('', 1) pdf.addImage(pageData, 'JPEG', 0, 10, imgWidth, imgHeight) if (index < resList.length - 1) { pdf.addPage() } if (index === resList.length - 1) { PDF.save(title + '.pdf') //pdf下载 if (typeof callback === 'function') { callback() } } }) }) } export { downloadPdf }

第三版:利用调后端上传文件的接口生成下载链接,PDF下载更改为a标签下载的方式

缺点:没有解决IOS下载失败的问题

实现代码:insPdfUtil.js文件

import html2canvas from 'html2canvas' import JsPDF from 'jspdf' //调接口 import constant from '@/common/constant' import store from '@/store' /** * 创建并下载pdf * html2canvas画是异步画图,所以这里需要用到promise.all * @param {HTMLElement} targetDom dom元素 * @param {String} title pdf保存名字 * @param {function} callback 回调函数 */ const downloadPdf = (targetList, title, callback) => { var pdf = new JsPDF('', 'pt', 'a4', true) const promiseList = [] targetList.forEach((item) => { promiseList.push( html2canvas(item, { useCORS: true, scale: 1 }) ) }) Promise.all(promiseList).then((resList) => { resList.forEach((item, index) => { var contentWidth = item.width var contentHeight = item.height // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 var imgWidth = 595.28 var imgHeight = (592.28 / contentWidth) * contentHeight var pageData = item.toDataURL('', 1) pdf.addImage(pageData, 'JPEG', 0, 10, imgWidth, imgHeight) if (index < resList.length - 1) { pdf.addPage() } if (index === resList.length - 1) { const file = pdf.output('blob') // 这样子后台就有名字了 const fileObject = new File([file], title + '.pdf', { type: 'application/pdf' }) uploadFileXHR(fileObject, (downloadUrl) => { // 利用a标签的download属性下载pdf,IOS不适用 const a = document.createElement('a') a.setAttribute('href', downloadUrl) a.download = title + '.pdf' a.click() if (typeof callback === 'function') { callback() } }) } }) }) } // --调后端接口的代码 const uploadFileXHR = (file, successUpload) => { const uploadUrl = `${constant.reqBaseUrl}/ins/file/tenantUploadFile` const data = { tenant: 'AKIAIOSFODNN7EXAMPLE', fileType: '5e25920b5b5b11e9bf97080027e99028', bucketName: 'papers' } const header = { token: store.getters.token } const formData = new FormData() for (const keys in data) { formData.append(keys, data[keys]) } formData.append('upload', file) const xhr = new XMLHttpRequest() xhr.open('POST', uploadUrl, true) for (const keys in header) { xhr.setRequestHeader(keys, header[keys]) } xhr.onreadystatechange = (ev) => { if (xhr.readyState === 4) { if (xhr.status === 200) { const data = JSON.parse(xhr.responseText) if (data.resCode === '0') { successUpload(data.data.preview_url) } } else { // } } } xhr.send(formData) } export { downloadPdf }

第四版:将后端生成的pdf文件地址通过webview通信传回APP,利用uniapp的uni.downloadFile和uni.saveFile下载文件

实现代码:1) insPdfUtil.js文件

..... // 封装的webview通信代码 import { postmessageJumpOnApp } from '@/common/utils/insWebviewUtil' ..... if (index === resList.length - 1) { const file = pdf.output('blob') // 这样子后台就有名字了 const fileObject = new File([file], title + '.pdf', { type: 'application/pdf' }) uploadFileXHR(fileObject, (downloadUrl) => { /* const a = document.createElement('a') a.setAttribute('href', downloadUrl) a.download = title + '.pdf' a.click() */ // ---------------- postmessageJumpOnApp(downloadUrl) if (typeof callback === 'function') { callback() } }) } .....

  2) app项目页面 pdfpages.vue

....... ...... methods: { message(e) { if (e &&e.detail && e.detail.data &&e.detail.data.length &&e.detail.data[0].jumpTo) { // 接受到weixin项目传过来的pdf文件地址 uni.downloadFile({ url: e.detail.data[0].jumpTo, success: (res) => { if (res.statusCode === 200) { var filePath = res.tempFilePath; uni.saveFile({ tempFilePath: filePath, success: function (res) { var savedFilePath = res.savedFilePath; uni.showToast({ icon:'none', mask:true, title:'文件已保存并即将打开', duration:1000 }) setTimeout(()=>{ uni.openDocument({ filePath: savedFilePath, success: function (res) { console.log('打开文档成功'); } }); },1000) }, fail:(err)=>{ uni.showToast({ icon:'none', mask:true, title:'文件下载失败', duration:1000 }) } }); } } }) return } }, } ......


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有