- <a-upload :file-list="objData.fileList" name="file" :beforeUpload="beforeUpload" class="zlcUpload">
- <a-button>
- <a-icon type="cloud-upload" />
- </a-button>
- </a-upload>
- <a-button size="large" type="primary" :disabled="!objData.fileList.length" @click="upload" class="zlcBtn">
- 上传
- </a-button>
- data() {
- return {
- objData: {
- chunkSize: 1 * 1024 * 1024,
- fileList: [],
- sliceList: [],
- md5: null,
- fileName: null,
- finishSliceList: [],
- uploadStart: 0
- },
- visible: false,
- uploadCompleted: false,
- }
- },
-
- methods: {
- beforeUpload(file) {
- this.objData.fileList = [file];
- return false;
- },
- }
- async upload() {
- this.visible = true;
- let file = this.objData.fileList[0];
- this.objData.fileName = file.name;
- let fileMd5 = await this.getFileMd5(file);
-
- if (file.size < this.objData.chunkSize) {
-
- } else {
- this.objData.sliceList = this.getSliceList(file);
-
- this.hadUpload().then(res => {
- if (res.message == '上传成功') {
- this.objData.uploadStart = this.objData.sliceList.length
- this.uploadCompleted = true
- return
- }
- let finishArr = res.result;
- this.objData.uploadStart = !finishArr ? this.objData.sliceList.length : finishArr.length;
- if (!finishArr.length ||( finishArr.length < this.objData.sliceList.length)) {
- //并发请求
- this.concurRequest(this.objData.sliceList, 3).then(res => {
- let { md5, fileName } = this.objData;
- console.log('并发请求结果', res)
- let rejectResp = res.some(item => item.code != 200) //是否有失败的
- if(!rejectResp){ //全部成功
- mergeFile({ md5, fileName }).then(res => {
- this.uploadCompleted = true
- })
- }else{
- //至少一个失败
- }
-
- })
- }else{
-
- }
- // //开始上传
- // let uploadList = this.objData.sliceList.map(item => {
-
- // if (finishArr.includes(item.flag.toString())) {
-
- // } else {
- // return new Promise((resolve, reject) => {
- // const formData = new FormData();
- // formData.append(`file`, item.blob);
- // formData.append(`index`, item.flag);
- // formData.append(`md5`, fileMd5);
- // formData.append(`filename`, file.name);
-
- // uploadFile(formData).then(res => {
- // this.objData.uploadStart++;
- // resolve(res);
- // }).catch(err => {
- // reject(err);
- // })
- // })
- // }
-
- // })
- // Promise.allSettled(uploadList).then(res => {
- // if (res.some(item => item.status == "rejected")) {
- // //至少一个分片失败
- // } else {
- // let { md5, fileName } = this.objData;
- // mergeFile({ md5, fileName }).then(res => {
- // this.uploadCompleted = true
- // })
- // }
- // })
-
-
- })
-
-
- }
- },
- //多线程获取md5唯一标识
- getFileMd5(file) {
- let that = this;
- return new Promise(resolve => {
- const worker = new Worker(new URL('@src/webWork/fileMd5.js', import.meta.url))
- // 向子线程发消息
- worker.postMessage(file)
- // 接收子线程发来的消息
- worker.onmessage = e => {
- that.objData.md5 = e.data
- resolve(that.objData.md5);
- worker.terminate();
- }
-
- })
- },
- //开始切片
- getSliceList(file) {
- let result = [];
- let index = 0;
- for (let nowSize = 0; nowSize < file.size; nowSize += this.objData.chunkSize) {
- result.push({
- flag: index,
- blob: file.slice(nowSize, nowSize + this.objData.chunkSize),
- })
- index++;
- }
- return result;
- },
- //判断之前是否上传过
- hadUpload() {
- let { fileName, md5 } = this.objData;
- return new Promise((resolve, reject) => {
- hadUploadFile({ fileName, md5 }).then(res => {
- resolve(res);
- }).catch(err => {
- reject();
- })
- })
- },
- //并发控制
- concurRequest(urls, maxNum){
- let that = this
- return new Promise(resolve => {
- let index = 0; //指向下一次请求的Url对应的下标
- let result = [] //保存请求的结果
- let count = 0; //当前完成请求的数量
- async function _request(){
- let i = index
- const url = urls[index]
- index++;
- try{
- // const resp = await fetch(url)
- const formData = new FormData();
- formData.append(`file`, url.blob);
- formData.append(`index`, url.flag);
- formData.append(`md5`, that.objData.md5);
- formData.append(`filename`, that.objData.fileName);
- const resp = await uploadFileCopy(formData, 2)
- console.log('请求结果', resp)
- result[i] = resp
- }catch(err){
- result[i] = err
- }finally{
- that.objData.uploadStart++;
- count++;
- if(count == urls.length){
- resolve(result)
- }
- if(index < urls.length){
- _request()
- }
-
- }
- }
- for(let i = 0; i < Math.min(urls.length, maxNum); i++){
- _request()
- }
- })
- }
- // worker.js ---子线程
- import SparkMD5 from "spark-md5"
- // 接收主线程发来的消息
- onmessage = (file) => {
- // 向主线程发送消息
- const reader = new FileReader();
- reader.readAsArrayBuffer(file.data);
- reader.onloadend = function (e) {
- const spark = new SparkMD5.ArrayBuffer();
- spark.append(e.target.result);
- let md5 = spark.end();
- postMessage(md5);
- };
- };
- //请求重试
- export const uploadFileCopy = (params, maxTimes) => {
- let initTimes = 0;
- let request = () => {
- return postRequest("/file/upload", params, {"Content-Type": "multipart/form-data"}).catch(err => {
- if(initTimes < maxTimes){
- initTimes++
- return request()
- }else{
- throw new Error('请求次数已达上限!')
- }
- })
- }
- return request()
- }