import axios from "axios";
import { getToken } from "@/utils/auth";
import { computed, ref } from "vue";
let fileSize;
const chunkList = ref([]);
export const getPercentage = computed(() => {
if (chunkList.value.length === 0) return 0;
const isAllSettled = chunkList.value.every((item) => item.percentage === 100);
if (isAllSettled) return 100;
const loaded = chunkList.value
.map((item) => item.size * item.percentage)
.reduce((arr, cur) => arr + cur);
return parseInt((loaded / fileSize).toFixed(2));
});
export const uploadSepcialFileByPieces = (url, { file, uploadId }) => {
const chunkSize = 5 * 1024 * 1024;
const chunkCount = Math.ceil(file.size / chunkSize);
fileSize = file.size;
const getChunkInfo = (file, index, chunkSize) => {
const start = index * chunkSize;
const end = Math.min(file.size, start + chunkSize);
const chunk = file.slice(start, end);
return { start, end, chunk };
};
const getFetchFormByReadChunk = (file, index, chunkSize, uploadId) => {
const { chunk } = getChunkInfo(file, index, chunkSize);
const fetchForm = new FormData();
fetchForm.append("file", chunk);
fetchForm.append("partNumber", +index + 1); // 分片数从 1 开始
fetchForm.append("uploadId", uploadId);
return fetchForm;
};
const uploadFile = (formData, i) => {
return axios({
url,
method: "post",
data: formData,
headers: {
Authorization: "Bearer " + getToken(),
"Content-Type": "multipart/form-data",
},
onUploadProgress: (data) => {
const { loaded, total } = data;
chunkList.value[i].percentage = parseInt((loaded / total) * 100);
},
});
};
const concurRequest = (uploadFile, forms, maxNum = 5) => {
return new Promise((resolve, reject) => {
const len = forms.length;
let index = 0;
let counter = 0;
const result = [];
const _request = async () => {
while (index < len && maxNum > 0) {
maxNum--;
const i = index;
const { formData, idx } = forms[index];
index++;
try {
const {
data: { code, msg, data },
} = await uploadFile(formData, idx);
result[i] = { code, msg };
if (code === 200) result[i].data = data;
} catch (error) {
reject(error);
} finally {
counter++;
maxNum++;
if (counter === len) {
const isAllSettled = result.every((item) => item.code === 200);
isAllSettled ? resolve(result) : reject(result);
} else {
_request();
}
}
}
};
_request();
});
};
return new Promise(async (resolve, reject) => {
try {
const formDataList = [];
for (let i = 0; i < chunkCount; i++) {
formDataList[i] = {
formData: getFetchFormByReadChunk(file, i, chunkSize, uploadId),
idx: i,
};
chunkList.value[i] = { size: chunkSize, percentage: 0 };
}
const result = await concurRequest(uploadFile, formDataList, 5);
resolve(result);
} catch (error) {
reject(error);
}
});
};
console