需求:某个固定的路径下,含有文件夹目录和文件,其中文件夹下可能还会有更深层的文件夹和文件,需要接口去请求判断,全部遍历完成后,全部文件夹及文件打包后下载。
使用插件:jszip、file-saver
1.思路分析
1)首先通过接口查一个文件夹路径下有哪些文件和文件夹;
2)如果是文件,写出文件内容;
3)如果是文件夹则需要递归查询这个文件夹下的文件及文件夹,直到没有嵌套更深层的文件夹为止;
4) 在遍历所有接口后,zip对象转为二进制流文件,使用file-saver插件(FileSaver.saveAs),或者自己创建一个a标签,使用URL.createObjectURL将二进制文件转为可下载的url对象,使用a.href也可以直接下载。
2.实现
npm install jszip file-saver
核心代码如下:
import JSZip from 'jszip';
const downloadAsZip = (path: string, zip: any) => {
// 这里调用查询某个path下文件及文件夹接口
return fetch(`url?path=${path}`, {method: 'get'}).then((res) => res.json()).then((res: any) => {
// 开始遍历
const promises = res.map((item: any) => {
if (item.is_fold) {
// 如果是文件夹,首先创建当前文件夹,然后传递当前路径和所在文件夹对象递归调用函数
const newFold = zip.folder(item.name);
return downloadAsZip(item.path, newFold)
} else {
// 如果是文件使用zip对象创建文件
// 请求文件时注意返回数据类型要设置blob类型
return axios({url: ``, method: 'get', responseType: 'blob'}).then((res:any) => {
zip.file(item.name, d?.data, { binary: true });
})
}
})
Promise.all(promises);
})
}
const zip = new JSZip();
let path = '/a';
const res: any = downloadAsZip(path, zip);
console.log(res);
3.下载操作
上文代码中注释已清楚写出了核心功能的实现方式,打印出的res是最后返回的promise对象我们then一下,然后在回调中进行到处文件包的操作:
// 方法一
res.then(() => {
zip.generateAsync({type: 'blob'}).then((content: any) => {
File.saver(content, 'dabao.zip')
})
})
// 方法二
res.then(() => {
zip.generateAsync({type: 'blob'}).then((content: any) => {
let a = document.createElement('a');
a.download = 'dabao.zip';
a.href = URL.createObjectURL(content);
a.click();
URL.revokeObjectURL(content);
})
})
注意:return的位置分析
调用递归方法,说到底需要返回promise是生成文件的axios方法:因为我们先看最外层,如果是文件直接返回了生成文件的axios方法,如果是文件夹则建立一个当前文件夹目录并递归去查询,最终是要等到遍历完所有文件为止,那么return写的位置就可以很好地理解了;