前端JSZip结合file-saver下载文件打包导出压缩文件

需求场景: 前端拿到下载文件的url,请求并将文件进行分类压缩生成压缩包导出

前端导出文件的优点:

  1. 减轻服务器负担: 后端生成压缩文件可能会占用服务器资源和时间。如果压缩的内容很大,可能会导致服务器压力增加,影响其他用户的访问速度。将这些任务转移到前端可以减轻服务器负担,提高整体系统的性能和稳定性。

  2. 用户体验: 前端实现可以提供更即时的用户反馈,用户可以立即看到下载进度和结果。此外,用户不需要等待服务器响应,可以立即开始下载,提高了用户体验。

  3. 灵活性和可控性: 前端可以更灵活地控制下载和压缩过程,根据用户的操作或需求进行相应的处理。例如,可以根据用户的选择动态生成压缩文件,或者根据用户的操作实时更新下载进度。

  4. 客户端资源利用: 前端实现可以充分利用客户端的计算资源,如浏览器的性能和内存,更高效地处理文件下载和压缩。

尽管在某些情况下,后端生成压缩文件可能更合适,特别是当需要处理大量或敏感数据时,为了确保安全性和数据完整性,可以在服务器端完成文件处理。但总体来说,在大多数情况下,将文件下载和压缩任务放在前端实现更为合适。

解决方案

使用jszip和file-saver插件

JSZipFileSaver 是 JavaScript 库,它们分别用于处理压缩文件和文件保存的操作。下面是它们的作用:

  1. JSZip: JSZip 是一个可以创建、读取和修改 ZIP 文件的 JavaScript 库。它允许你在客户端(浏览器)中动态生成 ZIP 文件,将多个文件或文件夹压缩成一个 ZIP 包,也可以解压已有的 ZIP 文件。在前端开发中,JSZip 可以用于在浏览器中生成和处理压缩文件,非常适合需要在客户端进行文件压缩和解压缩的场景。

  2. FileSaver: FileSaver 是一个用于在客户端保存文件的 JavaScript 库。它提供了一种简单的方式来将数据保存为本地文件,通常用于在浏览器中将动态生成的内容(如图像、文档、压缩文件等)保存到用户的计算机上。FileSaver 可以将 Blob 或 File 对象保存为本地文件,支持设置文件名和文件类型,非常适合用于下载动态生成的文件。

在需要的情境中,JSZip 用于在客户端中创建和处理压缩文件,将多个文件打包成一个 ZIP 文件;而 FileSaver 则用于在客户端将生成的 ZIP 文件保存到用户的计算机中,以供用户下载和使用。这两个库通常结合使用,能够方便地处理前端的文件压缩和下载需求。

实现方法

npm i file-saver@2.0.5
npm i jszip@3.10.1

页面中应用

import JSZip from 'jszip'
import FileSaver from 'file-saver'
 downloadPdf () {
      let title = '测试' 
      const flag = [
        'o2dTk5MjJmcHRucmh0dDRJOUZHRlhpZmxQWFZiTlh5VUZ5VWI5az0', // 请求参数
        'axaVMyeXhYbitFTWtwaFdZNTZIMzdQcTM4RE5JeFBuZENpMElJZz0',
        'T2h0QS9UekxzRaZEF0QTM4V2ZQRzl0U25SVGpEcWI3YW1ITm5yWT0',
        'MjFFV0xxx2SEM3RVJDZzNlUCtHRUdkcUtpU0UySHZWakFlQXBUTT0',
        'b1ZnYjY1OG3433RmhDb09NS1lOOUxocVFVcEZtZXBQb1BXendWbz0'
      ]
      const loading = this.$loading({ // 加载状态
        lock: true,
        text: '正在导出,请等待。。。',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
       // 这里的应用场景是页面中有多个附件需要下载导出 
      // 创建一个 promises 数组,用于存储每个请求的 promise 循环请求
      const promises = flag.map((id) => {
        return axios({
          url: `/frontend/api/common/downloadattchment?id=${id}&type=download`,
          method: 'GET',
          responseType: 'blob' // important
        })
      })
      // 使用 Promise.all 等待所有请求完成
      Promise.all(promises).then((responses) => {
        var zip = new JSZip()
        // 遍历每个请求的响应
        responses.forEach((response, index) => {
          const disposition = response.headers['content-disposition'] // 获取 HTTP 响应中头部字段 获取下载文件的文件信息
          const matches = /filename="(.+?)"/.exec(disposition) // 获取文件名
          const fileName = matches !== null && matches[1] ? matches[1] : `file${index + 1}`
          let decodedFileName = decodeURIComponent(fileName) //  URL 解码文件名
          const fileType = fileName.split('.').pop() // 获取文件类型后缀名
          const url = response.data
          // 添加文件到压缩包中
          zip.folder('报告').file(`${decodedFileName}.${fileType}`, url)
        })
        // 获取PDF文件并添加到压缩包中这里是单独获取base64编码格式的pdf图片数据 由base64                        
        转换为bolb二进制文件流
        getSinglePdf(title, 'pdfWarp').then((res) => {
          if (res) {
            let pdfBase64Str = res.split(';base64,')
            let byteCharacters = atob(pdfBase64Str[1])
            let byteNumbers = new Array(byteCharacters.length)
            for (let i = 0; i < byteCharacters.length; i++) {
              byteNumbers[i] = byteCharacters.charCodeAt(i)
            }
            let byteArray = new Uint8Array(byteNumbers)
            let pdfBlob = new Blob([byteArray], { type: 'application/pdf' })
            zip.folder('PDF').file(`${this.reportInfo.title.slice(0, this.reportInfo.title.indexOf(':'))}.pdf`, pdfBlob)
            // 生成并下载压缩文件  compression压缩模式 DEFLATE:可以压缩 STORE:不进行压缩,直接存储原始数据。 level压缩等级1-9 1最快9压缩率最高
            // compressionsh: BZIP2:使用 BZIP2 算法进行压缩。BZIP2 通常提供了更高的压缩率,但可能会稍微慢一些。 LZMA:使用 LZMA 算法进行压缩。LZMA 通常提供了最高的压缩率,但也是最慢的。
            zip.generateAsync({ type: 'blob', compression: 'DEFLATE', compressionOptions: { level: 9 } }, (data) => {
              const { percent } = data // 导出进度
              if (percent === 100) {
                loading.close()
              }
              console.log(percent, 'percent')
            }).then(function (content) {
              // 使用 FileSaver 保存下载 zip 文件
              FileSaver.saveAs(content, `${title}.zip`)
            })
          }
        })
      })
    },

导出后效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值