当前位置:   article > 正文

uniapp实现将页面转换成pdf(小程序、app、h5)_微信小程序页面转pdf

微信小程序页面转pdf

使用html2Canvas和jspdf

安装这两个

npm i jspdf html2canvas 

uniapp在小程序无法获取dom,app端可在renderjs中获取 dom,小程序需要使用web-view导入一个h5页面,实现转pdf

H5和小程序
  1. <template>
  2. <div>
  3. <div id="content">
  4. 要转换的内容
  5. </div>
  6. <button type="button" class="btn btn-primary" @click="getPdf()">导出PDF</button>
  7. </div>
  8. </template>
  9. <script>
  10. import html2Canvas from 'html2canvas'
  11. import { jsPDF } from 'jspdf'
  12. let BaseUrl = 'url' //域名
  13. export default{
  14. methods:{
  15. getPdf(){
  16. let that = this
  17. var shareContent = document.getElementById('content');
  18. var width = shareContent.offsetWidth / 4;
  19. var height = shareContent.offsetHeight / 4;
  20. html2Canvas(shareContent , {
  21. dpi: 900,
  22. scrolly: 0,
  23. // width:eleW,//生成后的宽度
  24. // height:eleH,//生成后的高度
  25. scrollx: -10,
  26. useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
  27. // backgroundColor: null //避免图片有白色边框
  28. }).then((canvas) => {
  29. var context = canvas.getContext('2d');
  30. context.mozImageSmoothingEnabled = false;
  31. context.webkitImageSmoothingEnabled = false;
  32. context.msImageSmoothingEnabled = false;
  33. context.imageSmoothingEnabled = false;
  34. var pageData = canvas.toDataURL('image/jpeg', 1.0);
  35. var img = new Image();
  36. img.src = pageData;
  37. img.onload = () => {
  38. // 获取dom高度、宽度
  39. img.width = img.width / 2;
  40. img.height = img.height / 2;
  41. console.log(img.width, '------ img.width');
  42. console.log(img.height, '------img.height');
  43. img.style.transform = 'scale(0.5)';
  44. if (width > height) {
  45. // 此可以根据打印的大小进行自动调节
  46. // eslint-disable-next-line
  47. var pdf = new jsPDF('l', 'mm', [width * 0.505, height * 0.545]);
  48. } else {
  49. // eslint-disable-next-line
  50. var pdf = new jsPDF('p', 'mm', [width * 0.505, height * 0.545]);
  51. }
  52. pdf.addImage(pageData, 'jpeg', 0, 0, width * 0.505, height * 0.545);
  53. pdf.save('安全服务协议' + '.pdf'); //h5在这就可以保存pdf
  54. //内嵌到微信小程序
  55. var blob = pdf.output("datauristring");
  56. console.log(wx,'wx')
  57. wx.miniProgram.getEnv(function (res) {
  58. console.log("当前环境:" + JSON.stringify(res));
  59. });
  60. wx.miniProgram.postMessage({
  61. data: {
  62. imageData:blob
  63. },
  64. });
  65. wx.miniProgram.navigateBack()
  66. };
  67. }).catch((r) => {
  68. console.log(r);
  69. })
  70. },
  71. },
  72. onLoad(e) {
  73. this.id = e.id
  74. }
  75. }
  76. </script>

其中通过web-view导入到微信小程序的话,需要导入微信的sdk

在index.html中导入也不知道咋回事,有wx,但是wx.miniProgram是undefined

<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>

然后网上找到大佬的方法

在App.vue里面写

  1. onLaunch: function() {
  2. console.log('App Launch')
  3. // #ifdef H5
  4. var script = document.createElement('script');
  5. script.src = "https://res.wx.qq.com/open/js/jweixin-1.4.0.js";
  6. script.type = 'text/javascript';
  7. document.body.appendChild(script);
  8. // #endif
  9. },

然后在小程序中使用web-view导入这个h5

  1. <template>
  2. <view class="">
  3. <web-view :src="url" @message="message"></web-view>
  4. </view>
  5. </template>
  6. <script>
  7. export default{
  8. data(){
  9. return{
  10. imageData:'',
  11. id:'',
  12. url:''
  13. }
  14. },
  15. methods:{
  16. message(e){
  17. console.log(e,'e')
  18. this.imageData = e.detail.data[0].imageData
  19. let path = this.imageData.split('base64,')[1]
  20. this.download(path)
  21. },
  22. async download(url) {
  23. let result = url.replace(/[\r\n]/g, '');
  24. var fs = wx.getFileSystemManager();
  25. let fileName = '';
  26. var times = new Date().getTime();
  27. url = wx.base64ToArrayBuffer(result);
  28. // console.log(url,'图片临时路径')
  29. const filePath = wx.env.USER_DATA_PATH + '/' + Date.now() + '.pdf'
  30. fs.writeFile({
  31. filePath,
  32. data: url, // 将 base64 转为 arrayuffer
  33. success (res) {
  34. uni.openDocument({
  35. showMenu: true,
  36. fileType: 'pdf',
  37. filePath,
  38. success: function (res) {
  39. console.log('打开文档成功')
  40. }
  41. })
  42. },
  43. fail (err) {
  44. console.log('错误', err)
  45. }
  46. })
  47. },
  48. },
  49. onLoad(e) {
  50. this.id = e.id || 0
  51. this.url = this.$http.BaseUrl+`/h5/#/?id=${this.id}`
  52. console.log(this.url,'url')
  53. }
  54. }
  55. </script>
App端

也可以使用web-view,但我直接在renderjs中写了

  1. <template>
  2. <div>
  3. <div id="content">
  4. 要转换的内容
  5. </div>
  6. <button type="button" class="btn btn-primary" @click="canvasImage.save">导出PDF</button>
  7. </div>
  8. </template>
  9. <script>
  10. import { base64ToPath } from '../../../common/imageTools.js';
  11. export default{
  12. methods:{
  13. receiveRenderData(url){
  14. this.loadBase64Url(url)
  15. },
  16. /* 将base64 位的图片路径转换为 临时路径 */
  17. loadBase64Url(url) {
  18. const imageStr = url;
  19. base64ToPath(imageStr)
  20. .then(path => {
  21. console.log(path,'path')
  22. this.saveImage(path);
  23. })
  24. .catch(error => {
  25. console.error('临时路径转换出错了:', error);
  26. });
  27. },
  28. saveImage(url){
  29. uni.saveFile({
  30. tempFilePath:url,
  31. async success(res) {
  32. uni.openDocument({
  33. filePath:res.savedFilePath,
  34. success: function(FileRes) {
  35. console.log('打开成功');
  36. }
  37. });
  38. },
  39. complete(res) {
  40. console.log(res,'res')
  41. }
  42. })
  43. },
  44. }
  45. }
  46. </script>
  47. <script lang="renderjs" module="canvasImage">
  48. import html2Canvas from 'html2canvas'
  49. import { jsPDF } from 'jspdf'
  50. export default {
  51. methods: {
  52. // 生成图片需要调用的方法
  53. generateImage(e, ownerFun) {
  54. return new Promise((resolve, reject) => {
  55. var shareContent = document.getElementById('content');
  56. var width = shareContent.offsetWidth / 4;
  57. var height = shareContent.offsetHeight / 4;
  58. html2Canvas(document.getElementById('content'), {
  59. dpi: 900,
  60. scrolly: 0,
  61. // width:eleW,//生成后的宽度
  62. // height:eleH,//生成后的高度
  63. scrollx: -10,
  64. useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
  65. // backgroundColor: null //避免图片有白色边框
  66. }).then((canvas) => {
  67. setTimeout(()=> {
  68. var context = canvas.getContext('2d');
  69. context.mozImageSmoothingEnabled = false;
  70. context.webkitImageSmoothingEnabled = false;
  71. context.msImageSmoothingEnabled = false;
  72. context.imageSmoothingEnabled = false;
  73. var pageData = canvas.toDataURL('image/jpeg', 1.0);
  74. // resolve(pageData)
  75. var img = new Image();
  76. img.src = pageData
  77. img.onload = () => {
  78. // 获取dom高度、宽度
  79. img.width = img.width / 2;
  80. img.height = img.height / 2;
  81. // console.log(img.width, '------ img.width');
  82. // console.log(img.height, '------img.height');
  83. img.style.transform = 'scale(0.5)';
  84. if (width > height) {
  85. // 此可以根据打印的大小进行自动调节
  86. // eslint-disable-next-line
  87. var pdf = new jsPDF('l', 'mm', [width * 0.505, height * 0.545]);
  88. } else {
  89. // eslint-disable-next-line
  90. var pdf = new jsPDF('p', 'mm', [width * 0.505, height * 0.545]);
  91. }
  92. pdf.addImage(pageData, 'jpeg', 0, 0, width * 0.505, height * 0.545);
  93. var url = pdf.output("datauristring");
  94. resolve(url)
  95. };
  96. }, 500);
  97. }).catch((r) => {
  98. console.log(r);
  99. })
  100. })
  101. },
  102. async save(e,ownerFun){
  103. let img = await this.generateImage().then()
  104. ownerFun.callMethod('receiveRenderData',img)
  105. },
  106. },
  107. }
  108. </script>

然后发现在ios中pdf中的网络路径的图片不显示,用过其他方法,太笨还是不行,只能转base64

  1. urlTobase64(url){
  2. return new Promise((resolve,reject)=>{
  3. uni.request({
  4. url: url,
  5. method:'GET',
  6. responseType:'arraybuffer',
  7. success: res => {
  8. let base64 = wx.arrayBufferToBase64(res.data); //把arraybuffer转成base64
  9. base64 = ('data:image/jpg;base64,' + base64).replace(/[\r\n]/g, "")
  10. resolve(base64)
  11. },fail: (e) => {
  12. resolve(url)
  13. console.log("图片转换失败");
  14. }
  15. })
  16. })
  17. },

资源绑定那个js下载居然还要vip -_-,imageTool.js如下

  1. function getLocalFilePath(path) {
  2. if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
  3. return path
  4. }
  5. if (path.indexOf('file://') === 0) {
  6. return path
  7. }
  8. if (path.indexOf('/storage/emulated/0/') === 0) {
  9. return path
  10. }
  11. if (path.indexOf('/') === 0) {
  12. var localFilePath = plus.io.convertAbsoluteFileSystem(path)
  13. if (localFilePath !== path) {
  14. return localFilePath
  15. } else {
  16. path = path.substr(1)
  17. }
  18. }
  19. return '_www/' + path
  20. }
  21. function dataUrlToBase64(str) {
  22. var array = str.split(',')
  23. return array[array.length - 1]
  24. }
  25. var index = 0
  26. function getNewFileId() {
  27. return Date.now() + String(index++)
  28. }
  29. function biggerThan(v1, v2) {
  30. var v1Array = v1.split('.')
  31. var v2Array = v2.split('.')
  32. var update = false
  33. for (var index = 0; index < v2Array.length; index++) {
  34. var diff = v1Array[index] - v2Array[index]
  35. if (diff !== 0) {
  36. update = diff > 0
  37. break
  38. }
  39. }
  40. return update
  41. }
  42. export function pathToBase64(path) {
  43. return new Promise(function(resolve, reject) {
  44. if (typeof window === 'object' && 'document' in window) {
  45. if (typeof FileReader === 'function') {
  46. var xhr = new XMLHttpRequest()
  47. xhr.open('GET', path, true)
  48. xhr.responseType = 'blob'
  49. xhr.onload = function() {
  50. if (this.status === 200) {
  51. let fileReader = new FileReader()
  52. fileReader.onload = function(e) {
  53. resolve(e.target.result)
  54. }
  55. fileReader.onerror = reject
  56. fileReader.readAsDataURL(this.response)
  57. }
  58. }
  59. xhr.onerror = reject
  60. xhr.send()
  61. return
  62. }
  63. var canvas = document.createElement('canvas')
  64. var c2x = canvas.getContext('2d')
  65. var img = new Image
  66. img.onload = function() {
  67. canvas.width = img.width
  68. canvas.height = img.height
  69. c2x.drawImage(img, 0, 0)
  70. resolve(canvas.toDataURL())
  71. canvas.height = canvas.width = 0
  72. }
  73. img.onerror = reject
  74. img.src = path
  75. return
  76. }
  77. if (typeof plus === 'object') {
  78. plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
  79. entry.file(function(file) {
  80. var fileReader = new plus.io.FileReader()
  81. fileReader.onload = function(data) {
  82. resolve(data.target.result)
  83. }
  84. fileReader.onerror = function(error) {
  85. reject(error)
  86. }
  87. fileReader.readAsDataURL(file)
  88. }, function(error) {
  89. reject(error)
  90. })
  91. }, function(error) {
  92. reject(error)
  93. })
  94. return
  95. }
  96. if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
  97. wx.getFileSystemManager().readFile({
  98. filePath: path,
  99. encoding: 'base64',
  100. success: function(res) {
  101. resolve('data:image/png;base64,' + res.data)
  102. },
  103. fail: function(error) {
  104. reject(error)
  105. }
  106. })
  107. return
  108. }
  109. reject(new Error('not support'))
  110. })
  111. }
  112. export function base64ToPath(base64) {
  113. return new Promise(function(resolve, reject) {
  114. if (typeof window === 'object' && 'document' in window) {
  115. base64 = base64.split(',')
  116. var type = base64[0].match(/:(.*?);/)[1]
  117. var str = atob(base64[1])
  118. var n = str.length
  119. var array = new Uint8Array(n)
  120. while (n--) {
  121. array[n] = str.charCodeAt(n)
  122. }
  123. return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
  124. }
  125. var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
  126. if (extName) {
  127. extName = extName[1]
  128. } else {
  129. reject(new Error('base64 error'))
  130. }
  131. var fileName = getNewFileId() + '.' + extName
  132. if (typeof plus === 'object') {
  133. var basePath = '_doc'
  134. var dirPath = 'uniapp_temp'
  135. var filePath = basePath + '/' + dirPath + '/' + fileName
  136. if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
  137. plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
  138. entry.getDirectory(dirPath, {
  139. create: true,
  140. exclusive: false,
  141. }, function(entry) {
  142. entry.getFile(fileName, {
  143. create: true,
  144. exclusive: false,
  145. }, function(entry) {
  146. entry.createWriter(function(writer) {
  147. writer.onwrite = function() {
  148. resolve(filePath)
  149. }
  150. writer.onerror = reject
  151. writer.seek(0)
  152. writer.writeAsBinary(dataUrlToBase64(base64))
  153. }, reject)
  154. }, reject)
  155. }, reject)
  156. }, reject)
  157. return
  158. }
  159. var bitmap = new plus.nativeObj.Bitmap(fileName)
  160. bitmap.loadBase64Data(base64, function() {
  161. bitmap.save(filePath, {}, function() {
  162. bitmap.clear()
  163. resolve(filePath)
  164. }, function(error) {
  165. bitmap.clear()
  166. reject(error)
  167. })
  168. }, function(error) {
  169. bitmap.clear()
  170. reject(error)
  171. })
  172. return
  173. }
  174. if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
  175. var filePath = wx.env.USER_DATA_PATH + '/' + fileName
  176. wx.getFileSystemManager().writeFile({
  177. filePath: filePath,
  178. data: dataUrlToBase64(base64),
  179. encoding: 'base64',
  180. success: function() {
  181. resolve(filePath)
  182. },
  183. fail: function(error) {
  184. reject(error)
  185. }
  186. })
  187. return
  188. }
  189. reject(new Error('not support'))
  190. })
  191. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/143445
推荐阅读
相关标签
  

闽ICP备14008679号