纯前端完成批量下载文件功能,可以下载任何文件,开箱即用
最近工作中遇到了一个批量下载文件的需求,要求在前端实现,本来打算在网上找一下CV完事。但是找一圈下来没有一个合适的,不是只支持下载图片,就是写的过于简略。无奈,只能自己搞!自己动手,丰衣足食,本着我为人人,人人为我的原则。特写下此篇博客,以供参考。
这个批量下载支持多种文件格式混合下载,下载结果都会放进一个压缩包中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <script src="./js/FileSaver.js"></script> <script src="./js/jquery-2.0.0.min.js"></script> <script src="./js/jszip.min.js"></script> <script src="./layer/layer.js"></script> <body> <button onclick="downlist()">下载</button> </body> <script> // 文件列表数组,支持线上路径和本地路径 let pafurl = [ { url: "https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1546500353,2204894501&fm=26&gp=0.jpg", name: "0.jpg" }, { url: "https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2771978851,2906984932&fm=26&gp=0.jpg", name: "1.jpg" }, { url: "https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3922290090,3177876335&fm=26&gp=0.jpg", name: "2.jpg" }, { url: "./pdf/0.pdf", name: "1.pdf" }, { url: "./pdf/2.xlsx", name: "2.xlsx" }, { url: "./pdf/3.docx", name: "3.docx" } ] // 压缩包名称 const downLoadName = "批量下载压缩包.zip"; // 点击下载按钮 function downlist() { /* 批量下载方法,传入文件列表, 路径key名称必须为url,文件key名必须为name 文件名称必须携带后缀且不能重复 */ dowmurls(pafurl).then(res => { console.log(res); // 下载成功的个数 let successCount = pafurl.length - res.errUrls.length; // 下载失败的个数 let errorCount = res.errUrls.length; if (res.code === "success") { // 下载失败的文件 console.log(res.errUrls); // 提示 layer.confirm(`${successCount}个文件获取成功,${errorCount}个文件获取失败`, { btn: ['确定', '取消'] }, function (e) { // 点击确定关闭弹框并下载 layer.close(e) // 利用file-saver保存文件 saveAs(res.content, downLoadName); }) } else { layer.alert("文件下载失败", { icon: 2 }) } }); } // 接收一个文件路径的集合 function dowmurls(fileUrls) { return new Promise((resolve, reject) => { if (fileUrls.length > 0) { const zip = new JSZip(); const cache = {}; const downAll = []; // 错误文件 const errlist = []; for (let key in fileUrls) { const promise = getFile(fileUrls[key].url).then(data => { // 成功的文件 if (data !== "downerr") { // 获取文件名 const file_name = fileUrls[key].name; // 逐个添加文件 zip.file(file_name, data, { binary: true }); // 保存文件 cache[file_name] = data; } else { // 保存错误文件 errlist.push(fileUrls[key]) } }) // 保存所有的文件 downAll.push(promise) } // 统一下载 Promise.all(downAll).then(() => { // 生成二进制流 zip.generateAsync({ type: "blob" }).then(content => { // 封装的返回文件 let resData = { // 状态码 code: "success", // 存放错误文件数据 errUrls: [], // 文件流数据 content: null, } // 判断是否存在错误文件 resData.errUrls = errlist.length > 0 ? errlist : [] // 判断错误文件的个数是否等于要下载的文件个数 errlist.length !== fileUrls.length ? resData.content = content : resData.code = "error" // 返回下载结果信息 resolve(resData); }) }) } }) } // 根据文件路径获取这个文件的文件流 function getFile(url) { return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 设置响应类型为ArrayBuffer对象,目的是让JSZip正确识别并下载 xhr.responseType = 'arraybuffer'; xhr.onreadystatechange = function (e) { // 判断获取文件的状态,非200时为获取异常,返回错误码 if (e.target.status === 200) { // 直接返回arraybuffer格式的文件 if (xhr.response) { resolve(xhr.response); } } else { resolve("downerr"); } } xhr.send(); }) }; </script> </html>
本篇采用的是原生js来实现,使用vue实现只需要改一下方法调用方式和引入一下 jszip 和 FileSaver就可以了,下面是程序运行截图
解压后就可以看到下载的文件了,希望能够帮助大家,给我评论个好用