根据项目需求封装的一个阿里云OSS上传组件,可进行图片上传和视频上传。
上组件代码:
<template>
<div>
<div v-if="uploadType == 'image'">
<el-upload
class="avatar-uploader"
:style="{ width: imgWidth + 'px', height: imgHeight + 'px' }"
action=""
:show-file-list="false"
:auto-upload="false"
:on-change="(file) => uploadImageOrVideo(file)"
>
<img
v-if="showUrl"
:src="OSSUrl(showUrl)"
class="avatar"
:style="{ width: imgWidth + 'px', height: imgHeight + 'px' }"
/>
<i
v-else
class="el-icon-plus avatar-uploader-icon"
:style="{
width: imgWidth + 'px',
height: imgHeight + 'px',
'line-height': imgHeight + 'px',
}"
></i>
</el-upload>
</div>
<div v-if="uploadType == 'video'" class="video-main">
<el-upload
v-show="!uploadProgress"
style="display: inline-block"
action=""
:multiple="false"
:auto-upload="false"
:show-file-list="false"
:on-change="(file) => uploadImageOrVideo(file)"
>
<el-button
style="margin-left: 10px"
type="normal"
size="small"
@click="uploadBefore"
>选择视频</el-button
>
</el-upload>
<el-button
v-if="!showProgress && uploadProgress"
style="margin-left: 10px"
type="normal"
size="small"
>视频上传中...</el-button
>
<div style="width: 150px" v-if="uploadProgress && showProgress">
<el-progress
:text-inside="true"
:stroke-width="20"
:percentage="uploadProgress"
></el-progress>
</div>
<el-button
v-if="uploadProgress && cancelUpload"
style="margin-left: 10px"
type="normal"
size="small"
@click="stopUpload"
>取消上传</el-button
>
<el-button
v-show="showUrl && !uploadProgress && videoPreview"
style="margin-left: 10px"
type="normal"
size="small"
@click="dialogVisible = true"
>视频预览</el-button
>
</div>
<el-dialog title="视频预览" :visible.sync="dialogVisible" width="650px">
<video
controls
:src="OSSUrl(showUrl)"
style="width: 600px; height: 400px"
/>
</el-dialog>
</div>
</template>
<script>
// 下载oss模块后,引入使用
import OSS from 'ali-oss'
let clientArr = []
export default {
props: {
uploadType: {//上传的类型:image-图片(默认),video-视频
type: String,
default: 'image'
},
showFileUrl: {//要显示的image/video在阿里云服务器上的地址
type: String,
default: ''
},
configureOSS: {//创建OSS实例所需的配置项: 示例:{region:'oss-cn-shenzhen',accessKeyId:'xxx',accessKeySecret:'xxx',stsToken:'xxx',timeout:'xxx',bucket:'xxx'}
type: Object,
},
// createOSS: {//是否在初始化时创建OSS实例
// type: Boolean,
// default: false
// },
imgWidth: {//图片宽度
type: String,
default: '196'
},
imgHeight: {//图片高度
type: String,
default: '146'
},
fileName: {//文件上传名-在阿里云的目录位置
type: String,
},
uploadHeaders: {//文件上传携带头部
type: Object,
},
videoPreview: {//是否开启视频预览
type: Boolean,
default: false
},
cancelUpload: {//是否开启取消上传功能
type: Boolean,
default: false
},
showProgress: {//是否显示上传视频的进度条
type: Boolean,
default: false
},
ossSign: {//此次的上传的辨别标识
type: String,
default: ''
}
},
data () {
return {
client: [],//OSS 上传图片实例(用于解析)
showUrl: '',//图片/视频地址
dialogVisible: false,//视频预览弹窗
uploadProgress: null,//视频上传进度
}
},
watch: {
showFileUrl (newVal) {
this.showUrl = newVal
},
configureOSS (newVal) {
if (this.configureOSS) {
// 创建oss实例:可用来解析图片或视频
this.client = new OSS(newVal)
this.showUrl = this.showFileUrl
} else {
this.$message.error('缺少OSS实例创建配置参数,请使用configureOSS传入配置参数');
}
}
},
computed: {
// 解析出图片/视频的阿里云访问链接
OSSUrl () {
return function (object) {
if (this.client !== null) {
// console.log(client.signatureUrl(object))
}
return this.client === null || !object || object.length === 0
? ''
: this.client.signatureUrl(object, { expires: 3600 * 12 })
}
},
},
methods: {
getVal () {
return clientArr
},
// 停止上传
stopUpload () {
console.log(this.ossSign, 99999);
if (clientArr.length > 0) {
let index = clientArr.findIndex(item => (item.id == this.ossSign && item.client != null));
if (clientArr[index].client) {
this.$emit('uploadSuccess', 'stop')
clientArr[index].client.cancel()
clientArr[index].client = null
}
}
},
// 上传视频或图片
async uploadImageOrVideo (file) {
// 避免标识id同一时间上传多个视频
if (clientArr.length > 0) {
if (clientArr.some(item => (item.client != null && item.id == this.ossSign))) {
return
}
}
// 创建一个oss实例
if (this.configureOSS) {
if (this.fileName) {
// 创建oss实例:可用来解析图片或视频
let client = new OSS(this.configureOSS)
clientArr.push({ id: this.ossSign, client: client })
let index = clientArr.findIndex(item => (item.id == this.ossSign && item.client != null));
this.$emit('createdOSS', 'create')
// 获取上传的本地视频的时长
var binaryData = [];
// 传入file中raw
binaryData.push(file.raw);
//获取视频或者音频时长
var fileurl = URL.createObjectURL(new Blob(binaryData));
//经测试,发现audio也可获取视频的时长
var audioElement = new Audio(fileurl);
audioElement.addEventListener("loadedmetadata", function (_event) {
//audioElement.duration就是视频时长
file.duration = audioElement.duration.toFixed(0);
});
this.uploadProgress = 0
const fileName = this.fileName + file.name.replace(/.+\./, '.')
clientArr[index].client.multipartUpload(fileName, file.raw, {
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB。
partSize: 1024 * 1024,
meta: {
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
},
headers: this.uploadHeaders,
// 上传进度回调
progress: (percent, checkpoint) => {
if (percent === 1) {
this.uploadProgress = null
clientArr[index].client = null
} else {
let resprogress = {
progress: Number((percent * 100).toFixed(2)),
ossSign: this.ossSign
}
this.$emit('uploadProgress', resprogress)
this.uploadProgress = Number((percent * 100).toFixed(2))
}
}
}).then(result => {
let res = {
duration: file.duration,
url: result.name,
ossSign: this.ossSign
}
this.$emit('uploadSuccess', res)
}).catch(err => {
if (err.name == 'cancel') {
this.uploadProgress = null
}
})
} else {
this.$message.error('上传的文件名不能为空!');
}
} else {
this.$message.error('缺少OSS实例创建配置参数,请使用configureOSS传入配置参数');
}
},
//
uploadBefore () {
this.$emit('uploadBefore', 'upload')
}
},
created () {
}
}
</script>
<style scoped>
.avatar-uploader {
border: 1px dashed #d9d9d9;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
/* width: 196px;
height: 146px;
line-height: 178px; */
text-align: center;
}
.avatar {
/* width: 196px;
height: 146px; */
display: block;
}
.video-main {
display: flex;
align-items: center;
}
</style>
-Oss组件封装使用文档
- vscode启动项目后,安装ali-oss模块。然后在需要使用的文件中引入组件,注册并使用。(注:组件中有使用element ui,需要引用此组件的项目提供运行环境支持),示例:
- 使用组件。示例:
组件相关参数
- 方法
参数 | 说明 | 类型 | 默认值 | 必传 |
uploadType | 上传的类型:image-图片,video-视频 | String | image | 否 |
showFileUrl | 要显示的image/video在阿里云服务器上的地址 | String | — | 否 |
configureOSS | 创建OSS实例所需的配置项: 示例:{region:'oss-cn-shenzhen',accessKeyId:'xxx',accessKeySecret:'xxx',stsToken:'xxx',timeout:'xxx',bucket:'xxx'} | Object | — | 是 |
imgWidth | 上传类型为image时,图片的宽度 | String | 196(仅传数值,固定px单位) | 否 |
imgHeight | 上传类型为image时,图片的高度 | String | 146(仅传数值,固定px单位) | 否 |
fileName | 文件上传名(在阿里云的目录地址) | String | — | 是 |
uploadHeaders | 文件上传是设置的头部请求(根据具体需求选择是否上传) | Object | — | 否 |
videoPreview | 是否开启视频预览 | Boolean | false | 否 |
cancelUpload | 是否开启取消上传功能 | Boolean | false | 否 |
showProgress | 是否显示上传视频的进度条 | Boolean | false | 否 |
ossSign | 此次上传的标识(批量上传时用于辨别) | String | — | 否 |
方法名 | 说明 | 备注 |
uploadSuccess | 上传成功回调 | |
uploadProgress | 上传进度回调 | 同时使用多个组件时,数据可能会错乱。 |
uploadBefore | 选择文件的触发事件 | 用于更新OSS示例参数 |
createdOSS | 创建OSS实例时触发 | 用于监听创建的OSS数量 |
版本:1.0.0
说明:初始版本,后面会陆续补充和优化内容。
实际应用中,发现短时间内可触发上传按钮两次,可能会创建出两个实例,因此补充获取组件创建上传实例的方法:getVal(),具体使用如下:
在调用组件的父级页面:
然后获取子组件的创建实例情况:
注:上传视频完成会销毁对应的OSS实例,所以client不为空的及存在实例数。
版本:1.0.1
说明:优化了OSS实例创建规则,增加了OSS实例数获取方式。