最近有个需求需要前端批量打包文件的需求,然后经过搜索,使用到了 jszip 和 file-saver 这两个 js 插件。
jszip 压缩插件,这个插件用起来个人觉得还算比较容易,官方文档下,仅仅需要几行代码便可以导出一个压缩包文件。
官方示例代码如下,写了简单的注释:
var zip = new JSZip(); // 初始化jszip对象
zip.file("Hello.txt", "Hello Worldn"); // 添加一个 hello.txt 文件,内容为 Hello World
var img = zip.folder("images"); // 生成一个 images 文件夹
img.file("smile.gif", imgData, {base64: true}); // 在 images 文件夹中加入一个 smile.gif 文件,内容为 base64,options 中 base64 要设置为 true
// 这里接下来是将文件流同步生成压缩文件,并使用 file-saver 保存导出
zip.generateAsync({type:"blob"}).then(function(content) {
// see FileSaver.js
saveAs(content, "example.zip");
});
在业务代码里面,由于有多个文件,所以我的代码里面写了的是循环遍历的的,具体代码如下:
<template>
<div>
<p>只要有一个文件下载失败,就停止下载</p>
<button @click="download(1)" >点击下载</button>
<br />
<p>忽略在下载失败文件,可以继续下载</p>
<button @click="download(2)" >点击下载</button>
</div>
</template>
<script>
export default {
name: 'BatchDownload',
data () {
return {
}
},
methods: {
// 只要有一个失败,那就就停止下载
async downloadAll1 (files, filename) {
let zip = new JsZip()
let isFault = false
for (let i = 0; i < files.length; i++) {
let folder = files[i]
let newFolder = zip.folder(folder.folderName)
await new Promise((resolve, reject) => {
return folder.files.reduce((accumulator, item, index) => {
return accumulator.then(() => fetch(item.url).then(resp => {
if (resp.status !== 200) {
reject(` ${folder.folderName} 的日志文件 ${item.name} 下载失败,已停止下载`)
} else {
return resp.blob()
}
}).then(blob => {
newFolder.file(item.name, blob)
if (index === folder.files.length - 1) {
resolve()
}
}))
}, Promise.resolve())
}).catch(err => {
this.$alert(err, '错误', {
confirmButtonText: '确定',
type: 'warning'
})
isFault = true
})
if (isFault) {
break
}
}
if (!isFault) {
zip.generateAsync({type: "blob"}).then(content => {
saveAs(content, `${filename}.zip`)
})
}
},
// 全部下载,失败了那就再文件名后面加上‘下载失败’
async downloadAll2 (files, filename) {
let zip = new JsZip()
let failedFiles = [] // 下载失败文件
let filesCount = 0 // 总文件
for (let i = 0; i < files.length; i++) {
let folder = files[i]
let newFolder = zip.folder(folder.vin)
await new Promise((resolve, reject) => {
return folder.files.reduce((accumulator, item, index) => {
filesCount++
return accumulator.then(() => fetch(item.url).then(resp => {
if (resp.status !== 200) {
reject(`${folder.vin}/${item.name}`)
} else {
return resp.blob()
}
}).then(blob => {
if (!blob) {
newFolder.file(`${item.name}.下载失败`, blob)
} else {
newFolder.file(item.name, blob)
}
if (index === folder.files.length - 1) {
resolve()
}
}))
}, Promise.resolve())
}).catch(err => {
failedFiles.push(err)
})
}
// 下载后提示文案
let htmlString = `<div>下载成功${filesCount - failedFiles.length}个文件,下载失败${failedFiles.length}个</div>`
if (failedFiles.length > 0) {
let filesHtmlString = '<div>失败文件列表如下:</div>'
failedFiles.forEach(ele => {
filesHtmlString += `<p>${ele}</p>`
})
htmlString += filesHtmlString
}
this.$alert(htmlString, '提示', {
confirmButtonText: '确定',
type: failedFiles.length > 0 ? 'warning' : 'success',
dangerouslyUseHTMLString: true
})
zip.generateAsync({type: "blob"}).then(content => {
saveAs(content, `${filename}.zip`)
})
},
download(s) {
let files = [
{
folderName: '123456',
files: [
{name: 'a.svg', url: 'http://localhost:8080/img/beian-icon.png'},
{name: 'b.svg', url: 'http://localhost:8080/img/beian-icon.png'}
]
},
{
folderName: '7890',
files: [
{name: 'c.svg', url: 'http://localhost:8080/img/beian-icon.png'},
{name: 'd.svg', url: 'http://localhost:8080/img/beian-icon.png'}
]
}
]
if (s === 1) {
this.downloadAll1(files, '文件集合')
} else {
downloadAll2(files, '文件集合')
}
},
}
}
</script>
<style lang="scss" scoped>
</style>
但是 ,在使用过程中发现了一些问题,比如我通过 ajax 请求下来文件,大小大概是 100MB 左右,但是 zip.file() 方法添加进去了,但是文件内容是报错的,导出的是空文件,我估计是浏览器限制或者浏览器内存限制了,希望有用到这个插件的朋友也说说使用体验。
再说一下,这个需求由于前端打包失败了,后面改成了直接下载好几个文件的那种办法,不过还是用 ajax 请求文件流,方便修改下载文件的名字。
最后
以上就是时尚万宝路最近收集整理的关于前端批量打包下载文件的全部内容,更多相关前端批量打包下载文件内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复