vue 根据word摸板导出word文档,并压缩为zip

文章介绍了如何利用JSZip、PizZip、docxtemplater等库读取Word模板,处理图片,将URL转换为ArrayBuffer,以及如何批量导出和压缩多个Word文档。在处理图片时,需要将图片链接转化为ArrayBuffer,并用docxtemplater的image-module处理。
摘要由CSDN通过智能技术生成

yarn add jszip@3.10.1

yarn add jszip-utils@0.1.0

yarn add pizzip@3.1.4

yarn add docxtemplater@3.29.5

yarn add docxtemplater-image-module-free@1.1.1

yarn add file-saver@2.0.5

 注意:这里的fileUrl必须是绝对路径,否则可能会报 is not zip的错误,请大家注意。

import ImageModule from 'docxtemplater-image-module-free'
import JSZipUtils from 'jszip-utils'
import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'


export const exportDocx = (fileUrl, data) => {
  return new Promise((resolve) => {
    // 读取并获得模板文件的二进制内容
    
    JSZipUtils.getBinaryContent(fileUrl, (error, content) => {
      // 创建一个PizZip实例,内容为模板的内容
      if (error) {
        throw error // 错误处理
      }
      const imageOpts = {
        getImage: async function (tagValue, tagName) {
            // 这里尝试了很多次,需要将图片链接转为ArrayBuffer,字节数组的形式。
          const res = await URLToArrayBuffer(tagValue)
          return res
        },
        getSize: function (img, tagValue, tagName) {
          return [120, 180]
        },
      }

      const imageModule = new ImageModule(imageOpts)

      let zip = new PizZip(content)
      // 创建并加载docxtemplater实例对象
      let doc = new Docxtemplater()
      doc.attachModule(imageModule)
      doc.loadZip(zip)
      doc.setOptions({ paragraphLoop: true, linebreaks: false })
      doc.compile()
      // 设置模板变量的值

      doc.renderAsync({ ...data }).then(() => {
        // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
        let out = doc.getZip().generate({
          type: 'blob',
          mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        })

        resolve({ out, data })

      })
    })
  })
}

这里将url地址转ArrayBuffer的方法有很多。我看网上很多都是先将转为base64然后转为ArrayBuffer。我没有按这种方式,我是发送了一次请求,响应类型为arraybuffer。

function URLToArrayBuffer(url) {
  return new Promise((resolve) => {
    const xhr = new XMLHttpRequest()
    xhr.open('GET', url, true)
    xhr.responseType = 'arraybuffer'

    xhr.onload = function () {
      if (xhr.status === 200) {
        resolve(xhr.response)
      }
    }

    xhr.send()
  })
}

然后就是批量导出word文档

我这里写一个demo
这是一个点击事件。

const arr = new Array(10);
const data = {}  // 渲染摸板需要的数据

const exportWord=()=>{
   const res = arr.map(async(item)=>{
        return await exportDocx('/word.docx',data);
    })
    // 这里会拿到10个 Promise对象,内容是是exportDocx 返回的Blob对象。
        const zip = new JSZip() //创建压缩对象

    res.forEach(async(ee,index)=>{
        const e = await ee
// 将文件存到zip中
        zip.file('word.docx',e.out, { base64: true,
          compression: 'DEFLATE', // STORE:默认不压缩 DEFLATE:需要压缩
          compressionOptions: {
            level: 9, // 压缩等级1~9    1压缩速度最快,9最优压缩方式
          },
        })
    })
    
// 等待res中的Promise状态都完成才执行。
    Promise.all(res).then(() => {
      console.log('zip', zip)
      zip
        .generateAsync({
          type: 'blob',
        })
        .then((content) => {
          FileSaver.saveAs(content, '详情.zip')
          this.load = false
        })
        .finally(() => {})
    })

}

word文档摸板如下: 比较特殊的就是在处理图片时。

{#url0}{%url0}{/url0} 这类似if条件语句。

#table需要table的格式为  table:[{url0:'123',url1:'123',...},{}]

 大概就这些了,有什么问题私信哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成序猿@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值