239 lines
7.0 KiB
Vue
239 lines
7.0 KiB
Vue
<template>
|
|
<div style="width:auto">
|
|
<!-- <p>downloadProcess:{{ downloadProcess }}%</p>
|
|
<button @click="downloadFile">下载</button>-->
|
|
<n-input
|
|
v-model:value="downloadFileID"
|
|
type="textarea"
|
|
placeholder="于此处粘贴输入取件码 多行也能正确识别"
|
|
:autosize="{
|
|
minRows: 3,
|
|
maxRows: 5
|
|
}"
|
|
/>
|
|
|
|
<n-flex justify="end" style="margin: 10px 0;position:relative">
|
|
<n-button type="error" @click="downloadFileID = null">清空输入</n-button>
|
|
<n-button type="primary" @click="praseInput">开始下载</n-button>
|
|
</n-flex>
|
|
<n-data-table
|
|
:columns="columns"
|
|
:data="downloadQuene"
|
|
:max-height="250"
|
|
:bordered="false"
|
|
:single-line="false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from "vue";
|
|
import aesjs from "aes-js";
|
|
import { Base64 } from "js-base64";
|
|
import { saveAs } from "file-saver";
|
|
import { useSettingStore } from "@/pinia/store";
|
|
import { sm4 } from "sm-crypto";
|
|
import {NInput,NFlex,NDataTable,NButton} from 'naive-ui'
|
|
|
|
var downloadFileID = ref();
|
|
|
|
const setting = useSettingStore();
|
|
|
|
// 服务端端口
|
|
const serverPort = setting.serverPort;
|
|
|
|
var baseUrl =
|
|
location.protocol + "//" + location.hostname + ":" + serverPort + "/";
|
|
// console.log(baseUrl);
|
|
|
|
const blob2Uint8Array = function(blob) {
|
|
return new Promise((resolve, reject) => {
|
|
let reader = new FileReader();
|
|
reader.readAsArrayBuffer(blob);
|
|
reader.onload = function() {
|
|
let buffer = reader.result;
|
|
let uint8array = new Uint8Array(buffer);
|
|
resolve(uint8array);
|
|
};
|
|
reader.onerror = function() {
|
|
reject(reader.error);
|
|
};
|
|
});
|
|
};
|
|
const decrypt = (key, data) => {
|
|
return blob2Uint8Array(data).then(data => {
|
|
// 无加密
|
|
if(key.length === 0){
|
|
return data
|
|
}
|
|
// SM4
|
|
if (key.length >= 34) {
|
|
key = key.substring(3);
|
|
// console.log([...data])
|
|
var decryptedBytes = new Uint8Array(
|
|
sm4.decrypt([...data], key, { output: "array" })
|
|
);
|
|
return decryptedBytes;
|
|
} else {
|
|
// AES
|
|
key = aesjs.utils.utf8.toBytes(key);
|
|
var aesCtr = new aesjs.ModeOfOperation.ctr(
|
|
key,
|
|
new aesjs.Counter(5)
|
|
);
|
|
var decryptedBytes = aesCtr.decrypt(data);
|
|
return decryptedBytes;
|
|
}
|
|
});
|
|
};
|
|
const decryptString = (key, str) => {
|
|
// 无加密
|
|
if(key.length === 0){
|
|
return sm4.decrypt(str, 'miaospringmiaospringmiaospringao');
|
|
}
|
|
// SM4
|
|
// console.log(key,key.length)
|
|
if (key.length >= 34) {
|
|
key = key.substring(3);
|
|
return sm4.decrypt(str, key);
|
|
}
|
|
// AES
|
|
var data = new Uint8Array(
|
|
Base64.decode(str)
|
|
.split(",")
|
|
.map(n => parseInt(n))
|
|
);
|
|
key = aesjs.utils.utf8.toBytes(key);
|
|
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
|
|
var decryptedBytes = aesCtr.decrypt(data);
|
|
var decryptedStr = aesjs.utils.utf8.fromBytes(decryptedBytes);
|
|
return decryptedStr;
|
|
};
|
|
|
|
const downloadFromUint8Array = (data, fileName) => {
|
|
let uint8Array = data;
|
|
let blob = new Blob([uint8Array], { type: "text/plain" });
|
|
// 使用file-saver.js
|
|
saveAs(blob, fileName);
|
|
|
|
//let url = URL.createObjectURL(blob);
|
|
//let a = document.createElement("a");
|
|
//a.href = url;
|
|
//a.download = fileName;
|
|
//a.click();
|
|
//URL.revokeObjectURL(url);
|
|
};
|
|
// 刷新展示的下载进度
|
|
const updateDownloadQuene = (code, key, value) => {
|
|
for (let index in downloadQuene.value) {
|
|
if (downloadQuene.value[index].code == code) {
|
|
downloadQuene.value[index][key] = value;
|
|
}
|
|
}
|
|
};
|
|
const praseInput = () => {
|
|
let codeArray = downloadFileID.value.split("\n");
|
|
for (let code of codeArray) {
|
|
if (
|
|
code === "" ||
|
|
downloadQuene.value.filter(m => m.code == code).length !== 0
|
|
)
|
|
continue;
|
|
// console.log(code);
|
|
let dp = {
|
|
code: code,
|
|
fileName: "有的事总是不得而知",
|
|
downloadProcess: "连接中。。。"
|
|
};
|
|
downloadQuene.value.push(dp);
|
|
downloadFile(code);
|
|
}
|
|
};
|
|
|
|
const downloadFile = code => {
|
|
var id = code.substring(0, 8);
|
|
var key = code.substring(8);
|
|
var fileName;
|
|
const params = {
|
|
fileName: id
|
|
};
|
|
const options = {
|
|
method: "GET"
|
|
};
|
|
fetch(baseUrl + "file/download?" + new URLSearchParams(params), options)
|
|
.then(res => {
|
|
fileName = res.headers.get("File-Name");
|
|
fileName = decryptString(key, fileName);
|
|
updateDownloadQuene(code, "fileName", fileName);
|
|
const total = +res.headers.get("Content-Length");
|
|
let loaded = 0;
|
|
|
|
const clone = res.clone();
|
|
const reader = res.body.getReader();
|
|
// 感觉怪怪的
|
|
const read = async () => {
|
|
const { done, value } = await reader.read();
|
|
if (done) {
|
|
// console.log(clone)
|
|
return clone;
|
|
}
|
|
loaded += value.length;
|
|
const percent = (loaded / total) * 100;
|
|
// downloadProcess['downloadProcess'] = `下载进度:${percent.toFixed(2)}%`;
|
|
updateDownloadQuene(
|
|
code,
|
|
"downloadProcess",
|
|
`下载进度:${percent.toFixed(2)}%`
|
|
);
|
|
// downloadProcess.value = percent.toFixed(2);
|
|
return read();
|
|
};
|
|
return read();
|
|
})
|
|
.then(res => {
|
|
var data = res.blob();
|
|
return data;
|
|
})
|
|
.then(data => {
|
|
// downloadProcess['downloadProcess'] = '解密中'
|
|
updateDownloadQuene(code, "downloadProcess", `解密中`);
|
|
decrypt(key, data).then(data => {
|
|
updateDownloadQuene(code, "downloadProcess", `已完成`);
|
|
downloadFromUint8Array(data, fileName);
|
|
});
|
|
})
|
|
.catch(err => {
|
|
updateDownloadQuene(
|
|
code,
|
|
"fileName",
|
|
`出错,可能是文件过期或下载次数用完`
|
|
);
|
|
updateDownloadQuene(code, "downloadProcess", `出错`);
|
|
console.error(err);
|
|
});
|
|
};
|
|
// 下载队列
|
|
const downloadQuene = ref([]);
|
|
const columns = [
|
|
{
|
|
title: "取件码",
|
|
key: "code",
|
|
width: 100
|
|
},
|
|
{
|
|
title: "文件名",
|
|
key: "fileName",
|
|
width: 100
|
|
},
|
|
{
|
|
title: "下载状态",
|
|
key: "downloadProcess",
|
|
width: 150
|
|
}
|
|
];
|
|
// 进度条进度
|
|
const progressPercentage = ref(60);
|
|
</script>
|
|
|
|
<style>
|
|
</style> |