前端(vue)导出word文档(导出图片)

前言:客户要求导出某功能里面的图片,于是乎想着用PDF导出,但无奈,图片是在太多了,PDF多页的时候,图片被截断(一部分在上一页,一部分在下一页),不停的调试代码处理这个,着实难以处理,最后只好放弃,换成word导出,依靠word文档的当前页装不下,自动放到下一页去。


导出word文档方法有很多,但这次要导出图片,所以选用了html-docx

html-docx是根据html代码进行导出

先引入html-docx

npm install html-docx --save

具体功能引入

import htmlDocx from 'html-docx'

但我这边是下载html-docx.js文件放在项目里面了,具体是引入还是下载js文件再引入看各自操作吧,js文件我放在文章里面,可以下载。


我的写法如下: 

import { asBlob } from 'htmlDocx.js文件存放路径'

先在HTML上面定义个DOM结构,作为导出格式,由于我只导出图片和一个标题,所以简单点了

    <!-- 导出Word使用, 样式自己定义,但一定要定义id或者ref,方便后期取到DOM结构 -->
    <!-- exportWordList 是要导出的数据,这里遍历它显示出来 -->
    <!-- 加个v-show隐藏起来,不让用户看到 -->
    <div ref="voucherWord" id="voucherWord" class="" v-show="false">
      <div v-for="(item, index) in exportWordList" :key="index">
        <!-- 标题 -->
        <div style="font-size: 15px; font-weight: bold;" class="">{{ item.title }}</div>
        <!-- 图片 -->
        <img v-if="item.imgList.length" v-for="(url, imgIndex) in item.imgList" :key="imgIndex" class="item img-x" :src="url" />
      </div>
    </div>

 导出方法

    // 导出Word
    async onExportWord () {
      // 将要要导出的数据
      const exportList = []
      // 处理后的导出数据
      const handlerExportList = []
      // 图片字段
      const imgFieldList = ['img', 'img1',.....]
      for (let index = 0; index <= exportList.length; index++) {
        // 当前行
        const row = exportList[index]
        // 图片base64集合
        const imgBa64List = []
        // 过滤出当前行图片字段有值的
        const currentRowImgFieldList = imgFieldList.filter(e => row[e])
        // 遍历图片字段
        for (let ai = 0; ai < currentRowImgFieldList.length; ai++) {
          const imgField = currentRowImgFieldList[ai]
          // 图片字段值,一个完成的url
          const url = row[imgField]
          // 根据url把图片转换成base64编码,这里加了await, 方法名前面必须得加async,把这个imageToBase64方法变成同步方法,imageToBase64方法后面再贴出来
          // 我的图片是随意排序,所以这里直接push base64的值了
          imgBa64List.push(await imageToBase64(url))
        }
        handlerExportList.push({
          title: row.title,
          imgList: imgBa64List
        })
      }
      this.exportWordList = handlerExportList
      // 等待HTML的DOM结构渲染完成
      this.$nextTick(() => {
        // 在等1.5秒,避免图片没有渲染完成
        setTimeout(() => {
          // 导出word文档
          // 取ref为voucherWord的DOM结构
          const htmlString = `
            <!DOCTYPE html>
            <html lang="en">
            <head>
              <meta charset="UTF-8">
              <title>Document</title>
            </head>
            <body>
              ${this.$refs.voucherWord.innerHTML}
            </body>
            </html>
          `
          // 用html-docx.js的asBlob方法把html结构转成word文档blob格式
          const blob = asBlob(htmlString)
          // 导出word,这里获得了blob,有很多种导出方法,可以用FileSaver.js(百度一下就有了),我这里就简单点了,用HTML的A标签导出
          // 获取下载链接
          const url = URL.createObjectURL(blob)
          // 页面上有一个a标签,A标签设置一下id或者ref,反正这里获取它的dom结构,用于下载Excel使用
          this.$refs.downloadFile.href = url
          // 设置excel名称
          this.$refs.downloadFile.download = '测试导出.docx'
          // 模拟点击一次a标签,执行下载
          this.$refs.downloadFile.click()
          // 清空要导出的数据
          setTimeout(() => this.exportWordList = [], 1000)
        }, 1500)
      })
    }

图片URL转base64方法(imageToBase64)

imageToBase64 (url, width, height) {
  return new Promise((resolve, reject) => {
    const image = new Image()
    image.src = url
    image.crossOrigin = '*'
    image.onload = () => {
      const canvas = document.createElement('canvas')
      canvas.width = width || image.width
      canvas.height = height || image.height
      const ctx = canvas.getContext('2d')
      ctx.drawImage(image, 0, 0, width || image.width, height || image.height)
      const base64 = canvas.toDataURL('image/png')
      resolve(base64)
    }
  })
}

有需要excel导出图片的,可以看我另一篇文章

前端(vue)exceljs导出Excel(导出图片)icon-default.png?t=N7T8https://blog.csdn.net/new_public/article/details/135657768


 码字不易,于你有利,勿忘点赞

人生得意须尽欢,莫使金樽空对月