import streamSaver from "streamsaver"; import "streamsaver/examples/zip-stream.js"; import JSZip from 'jszip'; import FileSaver from 'file-saver'; import axios from 'axios' // import store from '@/store' streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0` function getFile(url) { return new Promise((resolve, reject) => { axios.get(url, { responseType: 'blob', }).then(res => { resolve(res.data) }).catch(err => { reject(err) }) }) } function addFilesRecursively(zip, structure) { Object.keys(structure).forEach((key) => { if (typeof structure[key] === "object" && !structure[key].size) { // 创建子文件夹 const subFolder = zip.folder(key); addFilesRecursively(subFolder, structure[key]); } else { // 添加文件 zip.file(key, structure[key], { binary: true }); } }); }; function createFloders(obj, arr, r) { let i = arr.shift() if (arr.length <= 0) { obj[i] = r } else { if (!obj[i]) { obj[i] = {} } createFloders(obj[i], arr, r) } } function zipFilesJsZip(zipName, files, obj = {}, callback) { return new Promise(resolve => { try { if (callback) { callback({ type: 'start' }) } console.log("同步下载打包开始时间:" + new Date()); files = formatFiles(files) const zip = new JSZip(); let all = [] files.forEach(file => { let res = getFile(file.url).then(r => { const arr = file.name.split('/') createFloders(obj, arr, r) if (callback) { callback({ type: 'downLoad', data: r }) } // zip.file(fileName, r, { binary: true }); }) all.push(res) }) Promise.all(all).then(() => { if (callback) { callback({ type: 'downLoaded', }) } addFilesRecursively(zip, obj) zip.generateAsync({ type: "blob", compression: "STORE", // STORE:默认不压缩 DEFLATE:需要压缩 compressionOptions: { level: 1 // 压缩等级1~9 1压缩速度最快,9最优压缩方式 } }).then((res) => { if (callback) { callback({ type: 'zipEnd', }) } console.log("同步下载打包结束时间:" + new Date()); FileSaver.saveAs(res, zipName) // 利用file-saver保存文件 }) }) } catch (err) { console.log(err) } }) } // 下载文件并压缩 function zipFiles(zipName, files) { return new Promise((resolve) => { try { console.log("同步下载打包开始时间:" + new Date()); // store.dispatch('trials/setUnLock', true) files = formatFiles(files) // 创建压缩文件输出流 const zipFileOutputStream = streamSaver.createWriteStream(zipName); // 创建下载文件流 const fileIterator = files.values(); const readableZipStream = new ZIP({ async pull(ctrl) { const fileInfo = fileIterator.next(); if (fileInfo.done) {//迭代终止 ctrl.close(); } else { let { name, url } = fileInfo.value; url = decodeUtf8(url); return fetch(url).then(res => { ctrl.enqueue({ name, stream: () => res.body }); }) } } }); if (window.WritableStream && readableZipStream.pipeTo) { // 开始下载 readableZipStream .pipeTo(zipFileOutputStream) .then(() => { console.log("同步下载打包结束时间:" + new Date()); // store.dispatch('trials/setUnLock', false) resolve(true) }).catch(err => { console.log(err); resolve(false) }); } else { resolve(false) } } catch (err) { console.log(err); resolve(false) } }) } // 下载文件并修改名称 async function updateFile(file, name) { return new Promise(async resolve => { try { // store.dispatch('trials/setUnLock', true) const fileOutputStream = streamSaver.createWriteStream(name); file = decodeUtf8(file); let res = await fetch(file); res.body.pipeTo(fileOutputStream).then(() => { // store.dispatch('trials/setUnLock', true) resolve(true) }).catch(err => { console.log(err) resolve(false) }); } catch (err) { console.log(err) resolve(false) } }) } // 同名文件修改名称 function formatFiles(files) { let fileObj = {}; files.forEach(file => { let arr = Object.keys(fileObj); if (!~arr.indexOf(file.name)) { fileObj[file.name] = 1; } else { let name = file.name; file.name = name.split(".")[0] + `(${fileObj[name]})` + name .substring(name.lastIndexOf('.')) .toLocaleLowerCase() fileObj[name]++; } }) return files; } function decodeUtf8(bytes) { let str = bytes.split('?'); let str2 = str[0].split('/'); let name = str2[str2.length - 1]; name = encodeURIComponent(name); str.shift(); str2.pop(); return str2.join("/") + '/' + name; } export async function downLoadFile(file, name, type = 'file', callback) { if (type === 'zip') return await zipFilesJsZip(name, file, {}, callback); return await updateFile(file, name) }