文件分片上传
<input type="file" />
fileUpload() {
const num = 1;
const file = document.querySelector('input[type=file]').files[0];
// const file = $("#file")[0].files[0];
// this.msg.split('').reverse().join()
// 声明一个FormData对象
const formData = new FormData();
const time = new Date().getTime();
// 每片文件大小为5M
const blockSize = 5 * 1024 * 1024;
const blockNum = Math.ceil(file.size / blockSize);
const nextSize = Math.min(num * blockSize, file.size);
const fileData = file.slice((num - 1) * blockSize, nextSize);
formData.append('file', fileData)
// 文件名
formData.append('name', file.name)
// 总片数
formData.append('chunks', blockNum.toString())
formData.append('md5', time.toString())
formData.append('uid', '13570')
let config = {
headers: {
'Content-Type': 'multipart/form-data;boundary = ' + new Date().getTime()
}
}
axios.post('http://xxx/fileUpload', formData, config).then(response => (
this.info = response
)).catch((error: Error) => { // 请求失败处理
console.log(error)
})
}
文件分片下载
axios.download = async (url: string, params: any = null, fileName: string = null, onDownloadProgress: (progressEvent: any) => {}) => {
// 提前请求头部信息获取文件大小
const response = await axios.head(url, {params})
const contentLength = response.headers["content-length"]
if (contentLength == null) {
Notification.error("下载文件资源不存在!")
return
}
// 是否支持分片传输
const canSplice = response.headers["accept-ranges"] == "bytes"
// 设置分片下载
let concurrency_num = 1; // 并发数量
let start = 0, end = -1
if (contentLength / SizeUnits.GigaByte > 0.2) { // > 500M
if (onDownloadProgress == null) {
Notification.info({title: "系统提示", message: `下载文件资源可能过大,请稍后...`, position: 'bottom-right', duration: 5000})
}
if (canSplice) {
concurrency_num *= Math.ceil(contentLength / SizeUnits.GigaByte * 10) // 设置并发下载数量: 1个线程下载100M
}
}
const result = {
filename: fileName,
mime: response.headers["content-type"],
blobMap: new Map<number, []>()
}
if (fileName == null) {
const dispositions = response.headers["content-disposition"].split(";");
const fileField = dispositions.filter(it => it.indexOf("filename=") > -1)
result.fileName = fileField.length > 0 ? fileField[0].split("=")[1] : new Date().getTime()
}
function finish() {
const blob_arr = []
for(let i = 0; i < concurrency_num;i ++) {
blob_arr.push(result.blobMap.get(i))
}
const blob = new Blob(blob_arr, {type: result.mime});
const blobUrl = URL.createObjectURL(blob);
const link = document.createElement("a");
link.setAttribute('download', result.fileName || Math.random().toString())
link.href = blobUrl;
// document.body.appendChild(link)
link.click();
// document.body.removeChild(link)
Notification.success({title: "系统提示", message: `资源文件[${link.getAttribute("download")}]下载完成,请查看下载列表!`, position: 'bottom-right', duration: 5000})
}
const splice = Math.ceil(contentLength / concurrency_num)
let finish_counter = 0
for (let i = 0; i < concurrency_num; i++) {
start = i * splice
end = (i + 1) * splice - 1
console.log("start thread : ", i)
axios.get(url, {
responseType: 'blob',
params,
headers: {
range: `bytes=${start}-${end > contentLength ? contentLength - 1 : end}`
},
onDownloadProgress
}).then((resp) => {
finish_counter += 1
console.log("result: ", i, finish_counter, concurrency_num, resp.data)
result.blobMap.set(i, resp.data)
if (finish_counter == concurrency_num) {
finish()
}
}).catch((error: Error) => {
Notification.error(error.message)
})
}
}
参考资料