通过input框拿到file对象后
// 通过SparkMD5插件来计算文件的md5
import SparkMD5 from 'spark-md5'
//计算文件的md5值
function computeMd5(file, uploadFile) {
return new Promise((resolve, reject) => {
//大文件分片读取并计算md5,提高速度
const chunkTotal = 100 //分片数
const chunkSize = Math.ceil(file.size / chunkTotal)
const fileReader = new FileReader()
const md5 = new SparkMD5()
let index = 0
const loadFile = uploadFile => {
uploadFile.parsePercentage.value = parseInt((index / file.size) * 100)
const slice = file.slice(index, index + chunkSize)
fileReader.readAsBinaryString(slice)
}
loadFile(uploadFile)
fileReader.onload = e => {
md5.appendBinary(e.target.result)
if (index < file.size) {
index += chunkSize
loadFile(uploadFile)
} else {
// md5.end() 就是文件md5码
resolve(md5.end())
}
}
})
}
// 文件上传前的准备工作
beforeUpload(){
let uploadFile = {}
uploadFile.name = file.name
uploadFile.size = file.size
uploadFile.parsePercentage = ref(0)
uploadFile.uploadPercentage = ref(0)
uploadFile.uploadSpeed = '0 M/s'
uploadFile.chunkList = null
uploadFile.file = file
uploadFile.uploadingStop = false
uploadFile.index = uploadFileList.value.length
uploadFileList.value.push(uploadFile)
let md5 = await computeMd5(file, uploadFile) //计算出文件的md5
uploadFile.md5 = md5
let res = await checkFileByMd5({ md5 }) //上传服务器检查,以确认是否秒传
if (Array.isArray(res)) { // 不秒传
uploadFile.chunkList = res
uploadFile.needUpload = true
} else { // 秒传
uploadFile.needUpload = false
uploadFile.uploadPercentage.value = 100
ElMessage.success('文件已秒传!')
dialogVisible.value = false
}
uploadChunk(file, 1, uploadFile)
}
function uploadChunk(file, index, uploadFile) {
let chunkSize = 1024 * 1024 * 24 //24mb
let chunkTotal = Math.ceil(file.size / chunkSize)
if (index <= chunkTotal) {
// 根据是否暂停,确定是否继续上传
let startTime = new Date().valueOf()
let exit = uploadFile.chunkList.includes(index)
// console.log("是否存在",exit);
if (!exit) {
if (!uploadFile.uploadingStop) {
// 分片上传,同时计算进度条和上传速度
// 已经上传的不在上传、
// 上传完成后提示,上传成功
let formdata = new FormData()
let start = (index - 1) * chunkSize
let end = index * chunkSize >= file.size ? file.size : index * chunkSize
let chunk = file.slice(start, end)
formdata.append('chunk', chunk)
let type = filterFileClassify(file.name)
let chunkForm = {
chunkSize: chunkSize,
chunkTotal: chunkTotal,
fileName: file.name,
fileSize: file.size,
index: index,
md5: uploadFile.md5,
type: type
}
uploadChunkFile(chunkForm, formdata).then(res => {
let endTime = new Date().valueOf()
let timeDif = (endTime - startTime) / 1000
//上传速度
uploadFile.uploadSpeed = (10 / timeDif).toFixed(1) + ' M/s'
uploadFile.chunkList.push(index)
//上传进度
uploadFile.uploadPercentage = parseInt((uploadFile.chunkList.length / chunkTotal) * 100)
if (index == chunkTotal) {
// 调后台接口
bindBigFile(currentId.value, res).then(() => {
ElMessage.success('文件上传成功!')
//uploadRef是 elementPlu 的 el-upload的节点对象
uploadRef.value.clearFiles()
})
}
uploadChunk(file, index + 1, uploadFile)
})
}
} else {
uploadFile.uploadPercentage = parseInt((uploadFile.chunkList.length / chunkTotal) * 100)
uploadChunk(file, index + 1, uploadFile)
}
}
}
//点击下载文件分片
function downloadChunk(index, file) {
isDowning.value = true
let chunkSize = 1024 * 1024 * 5
let chunkTotal = Math.ceil(file.size / chunkSize)
if (index <= chunkTotal) {
// console.log("下载进度",index);
let exit = file.chunkList.includes(index)
console.log('存在', exit)
if (!exit) {
if (!file.downloadingStop) {
let startTime = new Date().valueOf()
downloadBigFile({
chunkSize: index * chunkSize >= file.size ? file.size - (index - 1) * chunkSize : chunkSize,
chunkTotal: chunkTotal,
fileName: file.name,
index: index,
md5: file.md5
}).then(res => {
file.chunkList.push(index)
let endTime = new Date().valueOf()
let timeDif = (endTime - startTime) / 1000
file.downloadSpeed = (5 / timeDif).toFixed(1) + ' M/s'
file.downloadPersentage = parseInt((index / chunkTotal) * 100)
const blob = res
file.blobList.push(blob)
//切片下载完成
if (index == chunkTotal) {
let resBlob = new Blob(file.blobList, {
type: 'application/octet-stream'
})
let url = window.URL.createObjectURL(resBlob) // 将获取的文件转化为blob格式
let a = document.createElement('a') // 此处向下是打开一个储存位置
a.style.display = 'none'
a.href = url
// 下面两行是自己项目需要的处理,总之就是得到下载的文件名(加后缀)即可
let fileName = file.name
a.setAttribute('download', fileName)
document.body.appendChild(a)
a.click() //点击下载
document.body.removeChild(a) // 下载完成移除元素
window.URL.revokeObjectURL(url) // 释放掉blob对象
//预览1.5s 浏览器处理文件
let timer = setTimeout(() => {
file.downloadPersentage = 100
isDowning.value = false
console.log('isDowning', isDowning.value)
//下载成功后,列表中清除当前的大文件
downloadingFileList.value.splice(
downloadingFileList.value.findIndex(ele => ele.id === file.id),
1
)
console.log(downloadingFileList)
if (downloadingFileList.value.length === 0) {
handleClose()
}
clearTimeout(timer)
timer = null
file = null
}, 1500)
}
downloadChunk(index + 1, file)
})
}
} else {
file.downloadPersentage = parseInt((index / chunkTotal) * 100)
downloadChunk(index + 1, file)
}
}
}