vue element-ui的upload组件直传视频到阿里云oss
element
A Vue.js 2.0 UI Toolkit for Web
项目地址:https://gitcode.com/gh_mirrors/eleme/element
免费下载资源
·
1.安装ali-oss
npm install ali-oss
2.封装oss通用上传js工具类
oss.js 工具类(oss的参数写在这里哦!)
'use strict'
import {
dateFormat
} from '@/utils/util'
var OSS = require('ali-oss')
export default {
/**
* 创建随机字符串
* @param num
* @returns {string}
*/
randomString(num) {
const chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
let res = ''
for (let i = 0; i < num; i++) {
var id = Math.ceil(Math.random() * 35)
res += chars[id]
}
return res
},
/**
* 创建oss客户端对象
* @returns {*}
*/
createOssClient() {
return new Promise((resolve, reject) => {
const client = new OSS({
region: 'oss-cn-qingdao', // 请设置成你的
accessKeyId: 'xxxxxxxxxxxx', // 请设置成你的
accessKeySecret: 'xxxxxxxxxxxx', // 请设置成你的
bucket: 'xxxxxxxxxxxx', // 请设置成你的
secure: true // 上传链接返回支持https
})
resolve(client)
})
},
/**
* 文件上传
* @param option 参考csdn: https://blog.csdn.net/qq_27626333/article/details/81463139
*/
ossUploadFile(option) {
const file = option.file
const self = this
return new Promise((resolve, reject) => {
const date = dateFormat(new Date(), 'yyyyMMdd') // 当前时间
const dateTime = dateFormat(new Date(), 'yyyyMMddhhmmss') // 当前时间
const randomStr = self.randomString(4)// 4位随机字符串
const extensionName = file.name.substr(file.name.indexOf('.')) // 文件扩展名
const fileName = 'video/' + date + '/' + dateTime + '_' + randomStr + extensionName // 文件名字(相对于根目录的路径 + 文件名)
// 执行上传
self.createOssClient().then(client => {
// 异步上传,返回数据
resolve({
fileName: file.name,
fileUrl: fileName
})
// 上传处理
// 分片上传文件
client.multipartUpload(fileName, file, {
progress: function(p) {
const e = {}
e.percent = Math.floor(p * 100)
// console.log('Progress: ' + p)
option.onProgress(e)
}
}).then((val) => {
console.info(val)
if (val.res.statusCode === 200) {
option.onSuccess(val)
return val
} else {
option.onError('上传失败')
}
}, err => {
option.onError('上传失败')
reject(err)
})
})
})
}
}
在src下的util文件创建utils.js工具类
/**
* 时间日期格式化
* @param format
* @returns {*}
*/
export const dateFormat = function(dateObj, format) {
const date = {
'M+': dateObj.getMonth() + 1,
'd+': dateObj.getDate(),
'h+': dateObj.getHours(),
'm+': dateObj.getMinutes(),
's+': dateObj.getSeconds(),
'q+': Math.floor((dateObj.getMonth() + 3) / 3),
'S+': dateObj.getMilliseconds()
}
if (/(y+)/i.test(format)) {
format = format.replace(RegExp.$1, (dateObj.getFullYear() + '').substr(4 - RegExp.$1.length))
}
for (const k in date) {
if (new RegExp('(' + k + ')').test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length === 1
? date[k] : ('00' + date[k]).substr(('' + date[k]).length))
}
}
return format
}
3.vue中的具体使用
<!-- 视频上传表单组件 -->
<template>
<div>
<!-- 上传dialog -->
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" :close-on-click-modal="false"
@close="cancel">
<el-form ref="form" :model="form" label-width="80px" size="small">
<el-form-item label="标题">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="副标题">
<el-input v-model="form.sub_title"></el-input>
</el-form-item>
<el-form-item label="视频封面">
<div class="crop-demo">
<img :src="cropImg" class="pre-img">
<div class="crop-demo-btn">选择图片
<input class="crop-input" type="file" name="image" accept="image/*" @change="setImage"/>
</div>
</div>
</el-form-item>
<el-form-item label="上传视频">
<el-upload class="upload-demo" action=""
:http-request="fnUploadRequest"
:show-file-list="true"
:limit=1
:on-exceed="beyondFile"
:on-success="handleVideoSuccess"
:before-upload="beforeUploadVideo">
<div tabindex="0" class="el-upload-video">
<i class="el-upload-video-i el-icon-plus avatar-uploader-icon"></i>
</div>
<div class="el-upload__tip" slot="tip">上传视频文件,且不超过500mb</div>
</el-upload>
</el-form-item>
<el-form-item label="所属类别">
<el-select v-model="form.category_id" placeholder="请选择">
<el-option key="1" label="美食" value="1"></el-option>
<el-option key="2" label="辅食" value="2"></el-option>
<el-option key="3" label="猫趣" value="3"></el-option>
<el-option key="4" label="猫生" value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item label="视频描述">
<el-input type="textarea" rows="5" v-model="form.description"></el-input>
</el-form-item>
<el-form-item label="选择状态">
<el-switch v-model="form.status"></el-switch>
</el-form-item>
<el-form-item>
<el-button @click="cancel">取消</el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="createData">添加</el-button>
<el-button v-else type="primary" @click="updateData">修改</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!-- end -->
<!-- 裁剪图片dialog -->
<el-dialog title="裁剪视频封面" :visible.sync="cropDialogVisible" width="30%">
<vue-cropper ref='cropper' :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage"
style="width:100%;height:300px;"></vue-cropper>
<span slot="footer" class="dialog-footer">
<el-button @click="cancelCrop">取 消</el-button>
<el-button type="primary" @click="cropDialogVisible = false">确 定</el-button>
</span>
</el-dialog>
<!-- end -->
</div>
</template>
<script>
import oss from '../../../utils/oss'
import VueCropper from 'vue-cropperjs'
export default {
components: {
VueCropper
},
props: {
dialogFormVisible: {
type: Boolean,
default: false
},
dialogStatus: {}
},
name: 'videoEdit',
data: function() {
return {
defaultSrc: './static/img/img.jpg',
fileList: [],
imgSrc: '',
cropImg: '',
cropDialogVisible: false,
textMap: {
update: '编辑视频',
create: '新增视频'
},
form: {
title: '',
sub_title: '',
category_id: '',
description: '',
status: true
}
}
},
created() {
this.cropImg = this.defaultSrc
},
methods: {
/**
* @description [fnUploadRequest 覆盖默认的上传行为,实现自定义上传]
* @param {object} option [上传选项]
* @return {null} [没有返回]
*/
async fnUploadRequest(option) {
oss.ossUploadFile(option)
},
// 视频上传
beforeUploadVideo(file) {
// todo
},
// 视频上传成功后
handleVideoSuccess(response, file, fileList) {
// todo
},
// 视频添加多个视频文件事件
beyondFile(files, fileList) {
// todo
},
cancel() {
this.$emit('ChangeVisible', false)
},
createData() {
this.$message.success('提交成功!')
},
updateData() {
this.$message.success('修改成功!')
},
setImage(e) {
const file = e.target.files[0]
if (!file.type.includes('image/')) {
return
}
const reader = new FileReader()
reader.onload = (event) => {
this.cropDialogVisible = true
this.imgSrc = event.target.result
this.$refs.cropper && this.$refs.cropper.replace(event.target.result)
}
reader.readAsDataURL(file)
},
cropImage() {
this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL()
},
cancelCrop() {
this.cropDialogVisible = false
this.cropImg = this.defaultSrc
}
}
}
</script>
<style lang="less" scoped>
.crop-demo {
display: flex;
align-items: flex-end;
}
.crop-demo-btn {
position: relative;
width: 100px;
height: 40px;
line-height: 40px;
padding: 0 20px;
margin-left: 30px;
background-color: #409eff;
color: #fff;
font-size: 14px;
border-radius: 4px;
box-sizing: border-box;
}
.crop-input {
position: absolute;
width: 100px;
height: 40px;
left: 0;
top: 0;
opacity: 0;
cursor: pointer;
}
.pre-img {
width: 100px;
height: 100px;
background: #f8f8f8;
border: 1px solid #eee;
border-radius: 5px;
}
.el-upload-video {
width: 100px;
height: 100px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.el-upload-video-i{
font-size: 36px;
padding-top: 25px;
color: #8c939d;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
}
</style>
4.视频分片上传失败
资源上传失败,提示
<Error>
<Code>InvalidPart</Code>
<Message>One or more of the specified parts could not be found or the specified entity tag might not have matched the part's entity tag.</Message>
<RequestId>5877284DE7D217CB1B39C200</RequestId>
<HostId>dxt-brand.oss-cn-shanghai.aliyuncs.com</HostId>
<ETag>undefined</ETag>
<PartNumber>1</PartNumber>
<UploadId>1FC722E82639475EB26E5D2A73A4F543</UploadId>
</Error>
这是啥情况呢,别慌,请修改此bucket的跨域设置里面的暴露 Headers增加一条ETag
5.你可能需要
GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45
7 个月前
a07f3a59
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update transition.md
* Update table.md
* Update table.md
* Update transition.md
* Update popover.md 7 个月前
更多推荐
已为社区贡献3条内容
所有评论(0)