<template>
<div class="uploadVideo">
<div class="videoBox" v-if="!url && !isUp">
<div class="upVideo" @click="inputChange">
<i class="el-icon-plus"></i>
</div>
</div>
<div class="videoBox">
<el-progress v-if="isUp" type="circle" :width="200" :percentage="videoUploadPercent"></el-progress>
</div>
<video id="vide" v-if="url" :src="url" class="videoAvatar" controls="controls"></video>
<div class="optionBtn">
<el-button type="primary" size="small" @click="inputChange" v-if="url">重新上传</el-button>
<el-button type="danger" size="small" @click="cancelUp" v-if="isUp">取消上传</el-button>
</div>
<p class="Upload_pictures">
<span>最多可以上传1个视频,建议大小50M,推荐格式mp4,点击视频重新上传</span>
</p>
<input class="inputer" ref="inputer" type="file" accept="video/*" @change="httpRequest" />
</div>
</template>
<script>
import OSS from 'ali-oss'
import {
v4 as uuidv4
} from "uuid"
import api from '@/api'
export default {
props: {
VideoPath: {
type: String,
default() {
return ''
}
}
},
data() {
return {
uploadImgUrl: process.env.VUE_APP_API + "upload-video", // 上传的视频服务器地址
videoFlag: false,
videoUploadPercent: 0,
cancel: false,
isUp: false,
url: '',
client: null
};
},
created() {
},
watch: {
VideoPath(val) {
this.url = val
},
},
methods: {
async httpRequest() {
this.isUp = true
this.videoUploadPercent = 0
this.url = ''
this.$emit('Change', '')
let that = this
let file = this.$refs.inputer.files[0]
var fileSize = file.size / 1024 / 1024 < 1000;
if (['video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb', 'video/mov'].indexOf(file.type) == -1) {
this.$notify.warning({
title: "警告",
message: "请上传正确的视频格式",
});
return false;
}
if (!fileSize) {
this.$notify.warning({
title: "警告",
message: "视频大小不能超过1000MB",
});
return false;
}
const { data } = await api.uploadParams()
if (!data.accessKeyID) {
return
}
this.client = new OSS({
region: data.region,
bucket: data.bucket,
stsToken: data.stsToken,
accessKeyId: data.accessKeyID, //AccessKey
accessKeySecret: data.accessKeySecret, //秘钥
});
const suffix = file.name.substr(file.name.indexOf('.'))
let url = '/video/' + uuidv4() + suffix
const options = {
// 获取分片上传进度、断点和返回值。
progress: (p, cpt, res) => {
this.videoUploadPercent = Math.floor(p * 100)
console.log(cpt)
if (this.cancel) {
this.client.abortMultipartUpload(cpt.name, cpt.uploadId)
this.cancel = false
}
},
// 设置并发上传的分片数量。
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB。
partSize: 1024 * 1024,
// headers,
// 自定义元数据,通过HeadObject接口可以获取Object的元数据。
// meta: { year: 2020, people: "test" },
mime: "text/plain",
};
try {
const {
res,
name
} = await this.client.multipartUpload(url, file, options)
if (res.status == 200) {
let videoUrl = 'https://y-video.ibookgames.com' + name
that.onSuccess(videoUrl)
}
} catch (e) {
that.onError('上传失败');
}
},
inputChange() {
this.$refs.inputer.click()
},
onError(e) {
this.url = ''
this.isUp = false
this.$emit('Change', '')
},
onSuccess(e) {
this.url = e
this.isUp = false
this.$emit('Change', e)
},
cancelUp(e) {
this.$refs.inputer.value = ''
this.cancel = true
},
}
};
</script>
<style scoped>
.uploadVideo {
display: flex;
flex-direction: column;
}
.videoAvatar {
width: 200px;
}
.optionBtn {
width: 200px;
display: flex;
align-items: center;
justify-content: center;
margin-top: 20px;
}
.upVideo {
width: 200px;
height: 100px;
border: 1px dashed#999999;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
position: relative;
}
.el-icon-plus {
font-size: 40px;
color: #999999;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.inputer {
width: 0;
height: 0;
position: absolute;
left: 0;
top: 0;
opacity: 0;
}
</style>
调用
<uploadImage :limit="6" ref="adtiveUp" @getUrl="ShowUrl($event, '自己需要携带的参数')"
@delUrl="ShowUrl($event, '自己需要携带的参数')" />
import utils from '@/utils/utils.js';
import store from '@/store'
import crypto from 'crypto-js';
import api from '@/request/index'
import {
v4 as uuidv4
} from 'uuid';
import {
Base64
} from 'js-base64'
// #ifdef APP-VUE
import permision from "@/common/permission.js"
// #endif
class Upload {
constructor(arg) {
this.uploadUrl = ''; // 上传文件地址
this.uploadList = []; // 上传文件列表
this.uploadCurrentIndex = 0; // 上传到第几个文件
this.uploadParams = {}; //上传参数
this.uploadLoading = true; //上传动画默认为true
this.sourceType = []; //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项
this.sizeType = []; //original 原图,compressed 压缩图,默认二者都有
}
// 选择图片
choiceImg() {
const that = this;
uni.chooseImage({
count: that.uploadParams.MaxNumber,
sourceType: this.sourceType,
sizeType: this.sizeType,
async success(res) {
const tempFilePaths = res.tempFilePaths;
that.uploadList = res.tempFiles;
if (that.uploadParams.MaxNumber && (that.uploadParams.MaxNumber < tempFilePaths.length)) {
utils.TextToast('超出文件上传最大数量' + that.uploadParams.MaxNumber);
that.ressetUpload();
} else {
that.uploadData();
}
},
fail(err) {
if (err.errMsg.indexOf('cancel') === -1) {
utils.TextToast('选择相册失败');
console.error(err);
}
},
complete() {
that.hideLoading();
}
});
}
upLoading(msg) {
utils.showLoading(msg || '上传中...', true)
}
hideLoading() {
utils.hideLoading();
}
// 上传文件
async uploadData() {
const that = this;
that.uploadLoading && that.upLoading();
let data = that.uploadParams.params
let fileData = that.uploadList[that.uploadCurrentIndex]
// 图片大小
const imgSize = fileData.size
if (imgSize > 10485760) {
utils.TextToast("图片超出大小限制,图片不得大于10M")
return false;
}
let newName = fileData.name || fileData.path
let name = uuidv4() + newName.substr(newName.lastIndexOf('.'))
let pramsData = await that.getFormDataParams()
uni.getImageInfo({
src: fileData.path,
complete(image) {
uni.uploadFile({
url: that.uploadUrl,
filePath: fileData.path,
formData: {
...pramsData,
key: name,
'success_action_status': '200',
},
fileType: 'image',
name: 'file',
success: (res) => {
const {
successBack,
failBack,
complateBack,
callback
} = that.uploadParams;
if (res.statusCode === 200) {
let url = that.uploadUrl + '/' + name
successBack(url);
// 根据 that.uploadCurrentIndex 判断是否需要继续上传图片
if (that.uploadCurrentIndex < that.uploadList.length - 1) {
that.uploadCurrentIndex += 1;
that.uploadData();
} else {
that.ressetUpload();
callback && callback();
}
} else {
that.ressetUpload();
failBack(data);
}
complateBack && complateBack(res);
},
fail(err) {
that.ressetUpload();
utils.TextToast('上传图片失败');
console.log(err);
}
});
}
});
}
computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
async getFormDataParams() {
const date = new Date();
date.setHours(date.getHours() + 1);
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
],
};
const credentials = await api('init.uploadParams')
this.uploadUrl = credentials.data.endpoint
const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。
const signature = this.computeSignature(credentials.data.accessKeySecret, policy)
const formData = {
OSSAccessKeyId: credentials.data.accessKeyID,
signature,
policy,
'x-oss-security-token': credentials.data.stsToken
}
return formData
}
// 上传完成后重置数据
ressetUpload() {
this.uploadCurrentIndex = 0;
this.uploadList = [];
this.uploadLoading && this.hideLoading();
}
async uploadMetod(paramsData) {
if (typeof paramsData !== 'object') {
throw Error('upload params is must a object');
}
this.uploadParams = paramsData;
this.uploadLoading = paramsData.uploadLoading !== undefined ? paramsData.uploadLoading : true;
this.sourceType = paramsData.sourceType !== undefined ? paramsData.sourceType : ['album', 'camera'];
this.sizeType = paramsData.sizeType !== undefined ? paramsData.sizeType : ['original', 'compressed'];
this.choiceImg();
}
}
export default new Upload()
调用
// 上传图片
async UploadImgs() {
let that = this
ossUp.uploadMetod({
MaxNumber: 1,
successBack(res) {
that.userInfo.bg_pic = res
that.setBg()
},
callback(res) {},
failBack(err) {
that.$utils.TextToast(err.message);
},
});
},