• jszip打包下载


    先说下网上给的解答方案:

    1、npm i jszip file-saver (axios)    ----axios一般第一次请求的时候就下载过了,如果没有,这里下载的时候加上axios

    2、引入这3个插件

    import axios from 'axios'
    import JSZip from 'jszip'
    import FileSaver from 'file-saver'

    3、定义getFile()函数,如果是这种格式的定义函数,写在export default {} 的上面

    const getFile = url => {
      return new Promise((resolve, reject) => {
        let obj = {
          method: 'get',
          url,
          // responseType: 'blob'
          responseType:'arraybuffer'
        }
        axios(obj)
          .then(data => {
            resolve(data.data)
          })
          .catch(error => {
            reject(error.toString())
          })
      })
    }

    4、利用jszip将文件挨个写入压缩包文件中

    export default {
      methods: {
        handleDownload() {
          const data1 = [
            'https://test-cloud-hospital-front.rubikstack.com/ms-hoc-material/v3/file/download/d1c8bc44c0f34f2f80778ad7a5222cfc.jpeg',
            // 'https://test-cloud-hospital-front.rubikstack.com/ms-hoc-material/v3/file/download/e9c12f0c8ae54ea8aa1e5de29a454b30.pdf',
            // 'https://test-cloud-hospital-front.rubikstack.com/ms-hoc-material/v3/file/download/0f7c01f52635460e9bb1de1a31fbda44.pdf',
            // 'https://test-cloud-hospital-front.rubikstack.com/ms-hoc-material/v3/file/download/851063dd3bf54219b6e6a03046f824ed.pdf'
          ]
          const zip = new JSZip()
          const cache = {}
          const promises = []
          data1.forEach(item => {
            const promise = getFile(item).then(data => {
              const arr_name = item.split('/') // 下载文件, 并存成ArrayBuffer对象
              const file_name = arr_name[arr_name.length - 1] // 获取文件名
              zip.file(file_name, data, { binary: true }) // 逐个添加文件
              cache[file_name] = data
              console.log(cache)
            })
            promises.push(promise)
          })
          Promise.all(promises).then(() => {
            zip.generateAsync({ type: 'blob' }).then(content => {
              console.log(content)
              // 生成二进制流
              FileSaver.saveAs(content, '文件下载.zip') // 利用file-saver保存文件  自定义文件名
            })
          })
        }
      }
    }

    接下来说下我自己的用法:

    先封装个组件再说,组件关系如下:

    Download.vue组件的完整代码:

    <template>
      <el-button @click="handleDownload">一键下载</el-button>
    </template>
    <script>
    import axios from 'axios'
    import JSZip from 'jszip'
    import FileSaver from 'file-saver'
    export default {
      data() {
        return {
          fileList: []
        }
      },
      created() {
        this.$observer.$on('downloadFileList', fileList => {
          console.log(fileList)
          this.fileList = fileList
        })
      },
      methods: {
        handleDownload() {
          const zip = new JSZip()
          const cache = {}
          const promises = []
          this.fileList.forEach(item => {
            const promise = this.getFile(item.fileUrl).then(data => {
              const file_name = item.fileName
              zip.file(file_name, data, { binary: true })
              cache[file_name] = data
            })
            promises.push(promise)
          })
          Promise.all(promises).then(() => {
            zip.generateAsync({ type: 'blob' }).then(content => {
              // 生成二进制流
              // FileSaver.saveAs(content, '文件下载.zip') // 利用file-saver保存文件  自定义文件名
              saveAs(content, '文件下载.zip') // 利用file-saver保存文件  自定义文件名
            })
          })
        },
        getFile(url) {
          return new Promise((resolve, reject) => {
            axios({
              method: 'get',
              url,
              responseType: 'blob'
              // responseType: 'arraybuffer'
            })
              .then(data => {
                console.log(data)
                resolve(data.data)
              })
              .catch(error => {
                reject(error.toString())
              })
          })
        }
      }
    }
    </script>

    说说踩得坑:

    一开始我通过axios去请求的时候,then()函数里返回的是

     data.data是一段二进制流字符串,这会导致下载下来的文件打不开,或者打开就是个空白,因为数据类型都是错的(应该返回的data.data是Blob类型的)。

    然后就开始了操蛋的找坑之路,各种百度,各种调试, 前端后端一起找原因,差点把我心态搞崩了。。。

    快要放弃的时候,准备直接用后端写的接口下载的时候,看到了这句话:mock模块会影响原生的ajax请求,使得服务器返回的blob类型变成乱码

    mock初始化的时候给拦截响应设置了responseType:''      这,这,这…跟谁讲道理去

    就算用原生也是不行:

    var zip = new JSZip()
    var eleLink
    var url = 'https://test-cloud-hospital-front.rubikstack.com/ms-hoc-material/v3/file/download/28b9af6a53154a02971ac6a4efebcd10.pdf'
    var xhr = new XMLHttpRequest()
    xhr.open('get', url, true)
    xhr.send()
    xhr.responseType = 'blob' // 返回类型blob
    
    xhr.onload = function() {
      if (this.status === 200) {
        console.log(this,this.response)
        let blob = new Blob([this.response])
        zip.file('smile.pdf', blob)
        zip.generateAsync({ type: 'blob' }).then(function(content) {
          saveAs(content, 'example.zip')
        })
      }
    }

    于是,我在main.js中将这个小B崽子注释掉了:

    然后数据就对了:

     OK!可以下载了!

    问题:

    1、responseType 设置blob和arraybuffer都可以下载:

    有知道的大佬可以给我留言

    2、FileSaver.saveAs(content, '文件下载.zip')   可以写成saveAs(content, '文件下载.zip'),这是不是就是说file-saver这个包是没用的,但是网上怎么都是jszip+file-saver的教程,知道的大佬麻烦留言~

    3、axios的封装,最好是封装出一个axios的实例,然后对这个实例进行操作

  • 相关阅读:
    JS获取URL中参数值(QueryString)的4种方法
    js 字符串转换成数字的 三种方法
    jquery.cookie 介绍 和 用法
    JS的document.all函数使用 示例
    JS按回车键实现登录的三种方法
    js 字符串转换成数字的三种方法
    GitHub访问速度慢的一种优化方法
    git commit 提交的时候报错husky > pre-commit hook failed (add --no-verify to bypass)
    git回退
    git commit 提交的时候报错husky > pre-commit hook failed (add --no-verify to bypass)(解决办法)
  • 原文地址:https://www.cnblogs.com/wuqilang/p/13567136.html
Copyright © 2020-2023  润新知