<template>
<div>
<el-upload class="upload-demo"
ref="upload"
action="#"
:file-list="fileList"
:http-request="httpRequest">
<el-button size="small"
type="primary">点击上传</el-button>
<div slot="tip"
class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
</div>
</template>
<script>
export default {
name: '',
components: {},
data() {
return {
fileList: [],
accept: '.png,.mp3'
}
},
methods: {
// 自定义上传,实现分片上传
httpRequest(param) {
const chunkSize = 3 * 1024 * 1024 //每个片的大小为3M
const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
const hasFile = (file) => {
return new Promise((resolve, reject) => {
const chunks = Math.ceil(file.size / chunkSize)
let currentChunk = 0
const SparkMD5 = window.SparkMD5
const spark = new SparkMD5()
const fileReader = new FileReader()
function loadNext() {
const start = currentChunk + chunkSize
const end = start + chunkSize >= file.size ? file.size : start + chunkSize
fileReader.readAsBinaryString(blobSlice.call(file, start, end))
}
fileReader.onload = (e) => {
spark.appendBinary(e.target.result)
currentChunk += 1
if (currentChunk < chunks) {
loadNext()
} else {
const hexHash = spark.end()
resolve(hexHash)
}
}
fileReader.onerror = () => {
this.$message.error('文件读取失败')
}
loadNext()
})
}
async function handleUplaod() {
const file = param.file
const type = file.name.match(/[^\.]\w+$/)[0].toLowerCase()
const uploadfile = this.$refs.upload.uploadfile
let uploadfileIndex = 0
if (!file) {
this.$message.error('没有获取文件')
return
}
if (!file.size) {
this.$message.error('文件内容为空')
return
}
if (this.accept && this.accept.indexOf(type) === -1) {
this.$message.error('文件类型错误')
return
}
if (file.size / 1024 / 1024 / 1024 / 5) {
this.$message.error('文件大小不能超过5GB')
return
}
uploadfile[getFileIndex(uploadfile, file.uid)].status = 'uploading'
const blockCount = Math.ceil(file.size / chunkSize) //分片总数
const hash = await hasFile(file) //文件md5
let totalCount = 0
checkFileStatus().then(res => {
if (!res.md5) {
// 服务器没有改文件 走上传
for (let i = 0; i < blockCount; i++) {
const start = i * chunkSize
const end = Math.min(file.size, start + chunkSize)
//参数
const form = new FormData()
form.append('file', blobSlice.call(file, start, end))
form.append('filename', file.name)
form.append('shardIndex', i)
form.append('md5', hash)
form.append('uid', file.uid)
form.append('shardTotal', blockCount)
// 上传
uploadShards(form, { md5: hash, name: file.name, shardTotal: blockCount, uid: file.uid })
}
} else {
// 有文件,直接拿文件数据
}
})
}
function getFileIndex() { return 0 }
function uploadShards(form, params) {
uploadShard(form).then(res => {
totalCount++
if (res.finishupload) {
// 所以分片完成,走合并
mege(params)
} else {
const uploadfile = this.$refs.upload.uploadFiles
for (let index = 0; index < uploadfile.length; index++) {
if (uploadfile[index].uid === file.uid && totalCount !== blockCount) {
uploadfile[index].percentage = Math.floor(totalCount / blockCount * 100)
}
}
}
})
}
function mege(arg) {
console.log(arg);
}
handleUplaod()
}
}
}
</script>
<style scoped>
</style>
大文件分片上传(自己备用,别人不一定看得懂)
于 2022-08-12 16:42:53 首次发布