前端 word 导出

前端的常规导出,一般是 excel,下载图片什么。word 的导出有点不太一样。

导出前的准备,安装相关依赖

import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import PizZipUtils from 'pizzip/utils/index.js'
import { saveAs } from 'file-saver'
import ImageModule from 'docxtemplater-image-module-free'

要新新建一个 word 的文件,中间的值用 {} ,类似于 tsx 或者 jsx 的写法,和 src 平级新建一个名称为 public 的文件夹

 

 

 index.docx 的内容

 

 

 第一个箭头,是常规的对象赋值,第二个,是表格循环,第三个是图片的显示

 

export const exportWord = ({ templateName = 'index.docx', docData = {}, fileName = '', fileType = 'docx' }: any) => {
  const base64DataURLToArrayBuffer = (dataURL: any) => {
    const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/
    const stringBase64 = dataURL.replace(base64Regex, '')
    let binaryString
    if (typeof window !== 'undefined') {
      binaryString = window.atob(stringBase64)
    } else {
      binaryString = Buffer.from(stringBase64, 'base64').toString('binary')
    }
    const len = binaryString.length
    const bytes = new Uint8Array(len)
    for (let i = 0; i < len; i++) {
      const ascii = binaryString.charCodeAt(i)
      bytes[i] = ascii
    }
    return bytes.buffer
  }
  const getBase64 = (img: any) => {
    function getBase64Image({ image, width, height }: any) {
      const canvas = document.createElement('canvas')
      canvas.width = width || image.width
      canvas.height = height || image.height

      const ctx: any = canvas.getContext('2d')
      ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
      var dataURL = canvas.toDataURL()
      return dataURL
    }
    var image = new Image()
    image.crossOrigin = ''
    image.src = img
    return new Promise((resolve, reject) => {
      image.onload = function () {
        resolve(getBase64Image({ image }))
      }
    })
  }

  loadFile(`/${templateName}`, function (error: any, content: any) {
    if (error) {
      throw error
    }
    const imageOpts = {
      getImage: async (tagValue: any, tagName: any) => {
        const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/
        let newValue: any = ''
        if (base64Regex.test(tagValue)) {
          newValue = base64DataURLToArrayBuffer(tagValue)
        } else if (tagValue.includes('http')) {
          await getBase64(tagValue).then((data) => {
            newValue = base64DataURLToArrayBuffer(data)
          })
        } else {
          await PizZipUtils.getBinaryContent(tagValue, function (error, content) {
            if (!error) {
              newValue = content
            }
          })
        }
        return newValue
      },
      getSize: function (img: any, tagValue: any, tagName: any) {
        return [150, 150]
      }
    }

    const imageModule = new ImageModule(imageOpts)

    const zip = new PizZip(content)

    const doc = new Docxtemplater()
      .loadZip(zip)
      .setOptions({
        paragraphLoop: true,
        linebreaks: true,
        nullGetter: nullGetter as any
      })
      .attachModule(imageModule)
      .compile()
    doc.renderAsync(docData).then(function () {
      const out = doc.getZip().generate({
        type: 'blob',
        mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
      })
      saveAs(out, `${fileName || new Date().getTime()}.${fileType}`)
    })
  })
}

图片的导出,如果是本地的话,填写正确的引入地址,也以直接导出 base64 格式的图片,网络图片,也是需要先转换成 bas464,再导出。网络图片导出有一个小坑,就是跨域问题。一般是用 jq 的一个方法,具体可以再查一下。

posted @ 2022-12-05 16:22  偷甜瓜香喷喷  阅读(482)  评论(0编辑  收藏  举报