vue实现阿里云批量上传
1、创建一个vue文件
<template>
<!-- 阿里云上传视频 支持批量上传 -->
<div id="uploadVideo">
<!-- 上传视频 dialog -->
<el-dialog
:title="$t('上傳視頻')"
:visible.sync="isUploadVideo"
center
width="1000px"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape = 'false'
>
<div>
<div class="upload-top">
<div class="upload-video-categoty">
<span>{{$t('视频分类',':')}}</span>
<el-select
:disabled="uploadDisabled"
v-model="uploadParam.videoTypeId"
:placeholder="$t('请选择视频分类')"
>
<el-option
v-for="item in videoCategoryList"
:key="item.videoManageCategoryId"
:label="item.name"
:value="item.videoManageCategoryId"
></el-option>
</el-select>
<span class="tip-text">{{$t('请先选择视频分类之后再上传视频')}}</span>
</div>
<el-upload
:disabled="uploadDisabled || uploadParam.videoTypeId==''"
class="upload-demo el-upload-dragger"
:show-file-list="false"
action="#"
multiple
:before-upload="beforeUploadVideo">
<i class="el-icon-upload"></i>
<div class="el-upload__text"><em style="color: #c0c0c0">{{$t('点击上传')}}</em><div style="color: #c0c0c0;font-size: 12px">{{$t('只能上传MP4文件,且不超过2GB')}}</div></div>
</el-upload>
</div>
<el-table
:data="UploadVideoList"
style="width: 100%;margin-top:20px"
height="400"
:header-cell-style="{background: '#f4f4f5'}"
tooltip-effect="dark"
border
>
<el-table-column prop="name" :label="$t('视频名称')">
<template slot-scope="scope">
<div class="video-message">
{{scope.row.file.name}}
</div>
</template>
</el-table-column>
<el-table-column prop="size" :label="$t('视频大小')">
<template slot-scope="scope">
<div>{{ scope.row.file.size | filterSize }}</div>
</template>
</el-table-column>
<el-table-column prop="size" :label="$t('进度')">
<template slot-scope="scope">
<el-progress :text-inside="true" :stroke-width="26" :percentage="scope.row.progressBar" :format="format"></el-progress>
</template>
</el-table-column>
<el-table-column prop="duration" :label="$t('操作')">
<template slot-scope="scope">
<span
type="danger"
class="ambow-btn-text-del"
style="margin:0;padding:10px;"
@click="onDelUploadVideoList(scope.row)"
>{{$t('刪除')}}</span>
</template>
</el-table-column>
</el-table>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="onDialogBtn()">{{$t('关闭')}}</el-button>
<el-button style="margin-left:10px;" type="primary" @click="onStartUpload" :disabled="isStartUpload">{{ $t('开始上传') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {uploadVideo} from "@/service/service";
var ossClient
export default {
name: "uploadVideo",
data(){
return {
uploadIndex:0,
isStartUpload:true,
UploadVideoList:[],
uploadDisabled:false,
uploadParam:{
firstImage: "",
sourceFilesize: "",
title: "",
url: "",
videoTimeSecond: "",
videoTypeId: ""
},
}
},
props:['isUploadVideo','videoCategoryList','uploadAliyunUrl'],
methods:{
onDelUploadVideoList(scope){
console.log(scope)
if(this.uploadDisabled){
this.$message.error('视频正在上传中,禁止删除')
return false
}else if(scope.progressBar>0){
this.$message.error('视频已上传完成,无法删除')
return false
}
this.$confirm($t('确定删除该数据','?'), $t('提示'), {
confirmButtonText:$t('确定'),
cancelButtonText:$t('取消'),
type: 'warning'
}).then(() => {
this.UploadVideoList.forEach((item,index)=>{
if(scope.file.name==item.file.name){
console.log('111')
this.UploadVideoList.splice(index,1)
this.$message.success($t('删除成功'))
}
})
}).catch(() => {
});
},
uploadVideo(){
console.log(this.uploadParam)
uploadVideo(this.uploadParam).then((res)=>{
console.log(res)
if(res.code==0){
if(this.uploadIndex+1==this.UploadVideoList.length){
this.uploadIndex+=1
this.uploadDisabled = false
this.isStartUpload = true
}else{
this.uploadIndex+=1
this.onUpload(this.UploadVideoList[this.uploadIndex],this.uploadIndex)
}
}
}).catch((err)=>{
console.log(err)
this.$message.error(err.msg)
})
},
restoreUpload(file,index){
let that = this
window.axios.get(this.uploadAliyunUrl, {}).then((res)=>{
let ossInfo = res.data;
ossClient = new OSS({
region: 'oss-cn-beijing',
accessKeyId: ossInfo.accessKeyId,
accessKeySecret: ossInfo.accessKeySecret,
bucket: ossInfo.bucketName,
stsToken: ossInfo.securityToken,
endpoint: 'oss-accelerate.aliyuncs.com',
secure: true
})
const options = {
progress:function(p,checkpoint){
that.UploadVideoList[index].progressBar = Number((p*100).toFixed(0))
},
checkpoint: that.tempCheckpoint,
partSize: 1000 * 1024,
timeout: 120000,
};
ossClient.multipartUpload(that.name, file.file,options).then(res=>{
console.log('360-1',res)
let url = ossClient.generateObjectUrl(that.name);
console.log(url)
that.uploadParam.firstImage = url+'?x-oss-process=video/snapshot,t_1000,m_fast'
that.uploadParam.sourceFilesize = file.file.size
that.uploadParam.title = file.file.name
that.uploadParam.url = url
that.uploadVideo()
}).catch((err)=>{
if(err.name=='cancel'){
this.$message.success($t('已取消上传'))
this.uploadDisabled = false
this.UploadVideoList = []
}else{
this.restoreUpload(file)
}
})
}).catch((err)=>{
console.log(err)
})
},
async onUpload(file,index){
function getDay(){
let time = new Date(),
year = time.getFullYear(),
month = time.getMonth() + 1 ,
day = time.getDate(),
timeStem = time.getTime();
return `huanyujun/${year}${month}/${timeStem}.MP4`
}
this.name = getDay()
this.uploadDisabled = true
let that = this
this.progressSeen = true
window.axios.get(this.uploadAliyunUrl, {}).then((res)=>{
let ossInfo = res.data;
ossClient = new OSS({
region: 'oss-cn-beijing',
accessKeyId: ossInfo.accessKeyId,
accessKeySecret: ossInfo.accessKeySecret,
bucket: ossInfo.bucketName,
stsToken: ossInfo.securityToken,
endpoint: 'oss-accelerate.aliyuncs.com',
secure: true
})
const options = {
progress:function(p,checkpoint){
that.UploadVideoList[index].progressBar = Number((p*100).toFixed(0))
that.tempCheckpoint = checkpoint
},
partSize: 1000 * 1024,
timeout: 120000,
};
ossClient.multipartUpload(that.name, file.file,options).then(res=>{
let url = ossClient.generateObjectUrl(that.name);
that.uploadParam.firstImage = url+'?x-oss-process=video/snapshot,t_1000,m_fast'
that.uploadParam.sourceFilesize = file.file.size
that.uploadParam.title = file.file.name
that.uploadParam.url = url
that.uploadVideo()
}).catch((err)=>{
if(err.name=='cancel'){
this.$message.success($t('已取消上传'))
this.uploadDisabled = false
}else{
that.restoreUpload(file,index)
}
})
}).catch((err)=>{
console.log(err)
})
},
format(percentage) {
return percentage === 100 ? $t('上传完成') : `${percentage}%`;
},
beforeUploadVideo(file){
if(file.size/1024/1024/1024 > 2){
this.$message.error($t('视频过大,请进行压缩后上传'));
return false
}
if(file.name.length>=100){
this.$message.error('视频名称过长');
return false;
}
if(this.uploadParam.videoTypeId==''){
this.$message.error('请先选择视频分类');
return false;
}
if (['video/mp4'].indexOf(file.type) == -1) {
this.$message.error('请上传正确的视频格式');
return false;
}
let videFile = {
file:file,
progressBar:0
}
this.UploadVideoList.push(videFile)
this.isStartUpload = false
console.log(this.UploadVideoList)
},
onStartUpload(){
if(this.UploadVideoList.length==0){
this.$message.error($t('请选择上传的视频'))
return false
}
this.onUpload(this.UploadVideoList[this.uploadIndex],this.uploadIndex)
this.isStartUpload = true
},
onDialogBtn(){
if(this.uploadDisabled>0){
ossClient.cancel();
}
this.uploadIndex = 0
this.uploadDisabled = false
this.UploadVideoList = []
this.$emit('onDialogBtn')
},
}
}
</script>
<style scoped>
.upload-top{
width: 100%;
height: 100%;
text-align: center;
}
/deep/ .el-upload-dragger{
width: 950px !important;
height: 125px !important;
}
/deep/ .el-icon-upload{
margin: 10px 0 16px;
}
.upload-video-categoty{
text-align: left;
margin-bottom: 10px;
display: flex;
align-items: center;
}
.video-m3u8{
width: 50%;
height: 50%;
position: fixed;
top: 200px;
left: 200px;
}
/deep/.el-upload{
width: 100% !important;
}
.tip-text{
margin-left: 10px;
color: #f56c6c;
}
</style>
2、在需要的组件中引用,并且传递需要的参数
import uploadVideos from './uploadVideo'
<uploadVideos :uploadAliyunUrl="'https://open-api.ambow.com/storage/api/v1/auth/ALIYUN/ambow/agora'" :isUploadVideo="isUploadVideo" :videoCategoryList="videoCategoryList" @onDialogBtn="onDialogBtn"></uploadVideos>
data(){
return {
isUploadVideo:false,
videoCategoryList:[],
}
}
onDialogBtn(){
this.isUploadVideo = false
this.getVideoList()
},
简单说一下注意的地方:
1、由于此次阿里云上传的是视频,所以会出现视频过大,导致阿里云的backName过期,上传不成功,这里需要用到阿里云的断点续传,在第一次上传时,创建一个全局变量ossClient来保存,在失败的时候调用,直到成功
2.有些视频需要封面设置,而阿里云也提供了相关方法,返回的url+‘?x-oss-process=video/snapshot,t_1000,m_fast’便是视频首图
const options = {
progress:function(p,checkpoint){
that.UploadVideoList[index].progressBar = Number((p*100).toFixed(0))
that.tempCheckpoint = checkpoint
},
partSize: 1000 * 1024,
timeout: 120000,
};
ossClient.multipartUpload(that.name, file.file,options).then(res=>{
let url = ossClient.generateObjectUrl(that.name);
that.uploadParam.firstImage = url+'?x-oss-process=video/snapshot,t_1000,m_fast'
that.uploadParam.sourceFilesize = file.file.size
that.uploadParam.title = file.file.name
that.uploadParam.url = url
that.uploadVideo()
}).catch((err)=>{
if(err.name=='cancel'){
this.$message.success($t('已取消上传'))
this.uploadDisabled = false
}else{
that.restoreUpload(file,index)
}
})
progress的回调中,p代表进度条,checkpoint代表上传进度,声明两个变量将其保存下来
const options = {
progress:function(p,checkpoint){
that.UploadVideoList[index].progressBar = Number((p*100).toFixed(0))
},
checkpoint: that.tempCheckpoint,
partSize: 1000 * 1024,
timeout: 120000,
};
在失败上传的方法中,需要重新读取阿里云地址,更新backName,然后将保存的progressBar 、checkpoint复制上去变实现了断点续传或者说分片上传