开发步骤
- 前端通过接口传文件名称给后端
- 后端生成签名 url 和 uuid 给到前端
- 前端使用 xhr 调用 minio 签名直传接口,完成大文件上传
- 前端根据 uuid 获取上传文件回显到页面
- 直传无法提供进度条,前端可根据宽带大致计算
文件上传实现
getPreSignedPutUrl({ fileName: file.name }).then(res => {
const uuid = res.data.uuid
axios.put(res.data.url, file, {
headers: { 'Content-Type': 'multipart/form-data' }
}).then(_ => {
getMinioFile({ uuid }).then(res => {
this.videoFile = res.data
}).catch(_ => {})
}).catch(_ => {
this.$message.error('上传错误,请稍后再试!')
this.videoLoading = false
})
}).catch(_ => {
this.videoLoading = false
})
优化体验!前端实现进度条
const fileSizeM = parseInt(file.size / 1024 / 1024)
let timerId
if (fileSizeM < 10) {
this.filePercentage = 50
} else {
const second = parseInt(fileSizeM / 10)
console.log('second', second)
const count = this.roundTo(100 / second, 2)
console.log('count', count)
timerId = setInterval(() => {
this.filePercentage += count
this.filePercentage = this.roundTo(this.filePercentage, 2)
console.log('this.filePercentage', this.filePercentage)
if (this.filePercentage > 99) {
this.filePercentage = 99
clearInterval(timerId)
}
}, 1000)
}
完整代码
import axios from 'axios'
import { getPreSignedPutUrl, getMinioFile } from '@/api/xxx.js'
export default {
data() {
return {
videoLoading: false,
filePercentage: 0,
videoFile: {}
}
},
methods: {
roundTo(num, decimals) {
const factor = Math.pow(10, decimals);
return Math.round(num * factor) / factor;
},
minioVideoRequest(event) {
const file = event.file
getPreSignedPutUrl({ fileName: file.name }).then(res => {
const fileSizeM = parseInt(file.size / 1024 / 1024)
let timerId
if (fileSizeM < 10) {
this.filePercentage = 50
} else {
const second = parseInt(fileSizeM / 10)
const count = this.roundTo(100 / second, 2)
timerId = setInterval(() => {
this.filePercentage += count
this.filePercentage = this.roundTo(this.filePercentage, 2)
if (this.filePercentage > 99) {
this.filePercentage = 99
}
}, 1000)
}
const uuid = res.data.uuid
axios.put(res.data.url, file, {
headers: { 'Content-Type': 'multipart/form-data' }
}).then(_ => {
clearInterval(timerId)
this.filePercentage = 100
setTimeout(() => {
this.filePercentage = 0
this.videoLoading = false
}, 500)
getMinioFile({ uuid }).then(res => {
this.videoFile = res.data
}).catch(_ => {})
}).catch(_ => {
this.$message.error('上传错误,请稍后再试!')
clearInterval(timerId)
this.filePercentage = 0
this.videoLoading = false
})
}).catch(_ => {
this.videoLoading = false
})
},
}
}
<el-form-item label="上传视频:" required>
<el-upload
:show-file-list="false"
:http-request="minioVideoRequest"
action=""
accept="video/*"
>
<el-button type="primary" size="small" :loading="videoLoading">本地上传</el-button>
</el-upload>
<div class="video-file">
<el-progress :percentage="filePercentage" v-if="videoLoading" />
<div v-if="videoFile.name">
<span>{{ videoFile.name }}</span>
</div>
</div>
</el-form-item>
验证:100M,11秒左右
