JSZip + FileSaver实现文件批量打包下载

前端实现文件批量打包下载。

JSZip

1
yarn add jszip file-saver

https://stuk.github.io/jszip/

FileSaver

1
yarn add file-saver

https://github.com/eligrey/FileSaver.js#readme

引入

1
2
import JSZip from 'jszip'
import saveAs from 'file-saver'

批量打包下载(Promise.all)

若有文件下载失败,将中断打包下载。

根据文件url获取文件二进制数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const getBlob = (item) =>
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', item.url, true)
xhr.responseType = 'blob'
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response)
} else {
reject('rejected reason')
}
}
xhr.ontimeout = () => {
reject('rejected reason')
}
xhr.onerror = () => {
reject('rejected reason')
}
xhr.send()
})

打包下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const zip = new JSZip()
const promises = []

data.forEach((item) => {
const promise = getBlob(item).then((blob) => {
// 获取文件名
let filename = item.title
// 获取文件扩展名
const filenameExtension = getFilenameExtension(item.url)
filename = `${filename}${filenameExtension}`
// 逐个添加文件
zip.file(filename, blob, { binary: true })
})
promises.push(promise)
})

Promise.all(promises)
.then(() => {
zip.generateAsync({ type: 'blob' }).then((content) => {
// file-saver保存文件
saveAs(content, `${downloadName}.zip`)
})
})

批量打包下载(Promise.allSettled)

对部分文件下载失败的情况做处理。

打包下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ... 同上

Promise.allSettled(promises).then((results) => {
const rejectedResults = results.filter(result => result.status === 'rejected')

if (rejectedResults.length) {
const reasons = rejectedResults.map(result => result.reason)
// 错误处理...
} else {
zip.generateAsync({ type: 'blob' }).then((content) => {
// file-saver保存文件
saveAs(content, `${downloadName}.zip`)
})
}
})