hir_web/src/utils/stream.js

197 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)
}