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的實例,然后對這個實例進行操作

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM