转载 https://blog.csdn.net/cxz792116/article/details/96906166
创建vue项目,并安装ali-oss
npm install ali-oss --save 或者 cnpm install ali-oss --save
1.单文件上传 下载简易示例代码如下:(只能单次上传,点击刷新页面会清除缓存,无法保存文件下载地址)
单文件效果图,上传时会有进度条动画
<template>
<div>
<el-upload
class="avatar-uploader"
action=""
:http-request="beginUpload"
:show-file-list="false">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<el-progress :percentage="Number(percentage.toFixed(2))"></el-progress>
<el-button @click="pauseUpload">暂停</el-button>
<el-button @click="goonUpload">继续</el-button>
<el-button @click="download">下载</el-button>
</div>
</template>
<script>
import OSS from 'ali-oss'
//定义全局变量,保存文件下载地址
var upurl = ''
export default {
components: {},
data () {
return {
imageUrl: '',
percentage: 0,
checkpoint: null,
client: null,
filename: '',
upurl: '',
}
},
computed: {
},
created () {
this.client = new OSS({
region: 'oss-cn-hangzhou',
accessKeyId: '<Your AccessKeyId>',
accessKeySecret: '<Your AccessKeySecret>',
bucket: 'Your bucket name',
secure: false
})
},
methods: {
//下载文件
download() {
//实现跳转到新的url,而不是在当前的地址后面追加url
window.location.href = upurl;
},
async ossUpload (filename, file) {
let _this = this
try {
let result = await _this.client.multipartUpload(filename, file, {
progress: async function (p, checkpoint) {
_this.checkpoint = checkpoint
_this.percentage = p * 100
},
checkpoint: _this.checkpoint
})
console.log(result)
} catch (e) {
console.log(e)
}
},
beginUpload (file) {
let _this = this
let filename = file.file.name
filename = filename.split('.')[0] + '_' + new Date().getTime() + '.' + filename.split('.')[1]
_this.file = file
_this.filename = filename
_this.ossUpload(filename, file.file)
//保存上传的文件下载地址
upurl = this.client.signatureUrl(_this.filename);
},
pauseUpload () {
this.client.cancel()
},
goonUpload () {
let file = this.file
let _this = this
_this.ossUpload(_this.filename, file.file)
}
}
}
</script>
2.多文件、多类型,异步上传(暂未封装完整)(只设置了能多次上传视频,其他类型的文件无法上传,需要重新设置判断条件)
效果图
<template>
<div id="upload-cp">
<a href="javascript:;" class="file">选择文件
<input type="file" :multiple="multiple" :accept="acceptType" id="uploadFile" @change="getFile($event)" />
</a>
<p v-if="isCount">选择了<span>{{file.length}}</span>个文件</p>
<el-button class="uploadBtn" :disabled="disabled" @click="upload" type="primary">上传</el-button>
</div>
</template>
<script>
/* eslint-disable */
import OSS from "ali-oss"
export default {
name: "Upload",
props:{
// 是否支持多文件上传
multiple:{
type: Boolean,
default: true
},
// 文件上传的个数限制
limitCount:{
type: Number,
default: 1,
},
// 文件上传的接受的类型 video/* :视频类型, image/*:图片,根据需要判断
acceptType:{
type: String,
default: 'video/*',
},
// 存放到 阿里云oss 对应的文件 video:视频, image: 图片, adjunct: 附件
storeType:{
type: String,
default: 'video',
}
},
data () {
return {
client: null,
loading: null,
file: null,
isCount: false,
disabled: false,
minW: 5, // 视频最小宽度
maxW: 1000000, // 视频最大宽度
minH: 5, // 视频最小长度
maxH: 100000, // 视频最大长度
minSize: 0.1, // 视频文件最大值
maxSize: 5000, // 视频文件最小值
minDurate: 0.1, // 视频时长最小值
maxDurate: 1000, // 视频时长最大值
fileInfo: [], // 上传oss成功后的返回值
videoLists: [], // 创建视频
videoSize: [], // 视频大小
videoRatio: [], // 视频分辨率
videoDurate: [], // 视频时长
}
},
created () {
this.client = new OSS({
region: 'oss-cn-hangzhou',
accessKeyId: '<Your AccessKeyId>',
accessKeySecret: '<Your AccessKeySecret>',
bucket: 'Your bucket name',
secure: false
})
},
mounted () {},
methods: {
// 开始动画
startLoading () {
this.loading = this.$loading({
lock: true,
text: '上传中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
},
// 结束动画
endLoading(){
this.loading.close()
},
// 获取文件路径
getObjectURL (file) {
let url = null
if (window.createObjcectURL != undefined) {
url = window.createOjcectURL(file)
} else if (window.URL != undefined) {
url = window.URL.createObjectURL(file)
} else if (window.webkitURL != undefined) {
url = window.webkitURL.createObjectURL(file)
}
return url
},
// 选择文件
getFile (event) {
this.disabled = false
this.file = event.target.files
for(let i = 0; i < this.file.length; i++){
let video = document.createElement('video')
video.setAttribute('controls', 'controls')
video.setAttribute('src', this.getObjectURL(this.file[i]))
this.videoLists.push(video)
this.videoSize.push(this.file[i].size / 1024 / 1024)
}
this.isCount = true
},
// 随机
random_string(len) {
len = len || 32;
let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz12345678', maxPos = chars.length, pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
},
// 日期
getDate(){
const date = new Date()
let year = date.getFullYear()
let month = date.getMonth() > 9 ? date.getMonth() + 1 : `0${date.getMonth() + 1}`
let day = date.getDate() > 9 ? date.getDate() : `0${date.getDate()}`
return `${this.storeType}/${year}${month}${day}/`
},
// 上传
upload () {
if(!this.file) return this.$message.error('请上传文件')
if(this.limitCount != this.file.length) return this.$message.error(`请上传${this.limitCount}个文件`)
// 这样需要根据 上传文件的类型进行再一次的封装,因为我这是以视频上传为主。后续进行完善
this.videoLists.map(item => {
this.videoDurate.push(item.duration)
this.videoRatio.push({h:item.videoHeight,w:item.videoWidth})
})
// 判断视频大小
let sizeBolean = this.videoSize.find((item) => {
return item < this.minSize || item > this.maxSize
})
// 判断视频时长
let durationBolean = this.videoDurate.find((item) => {
return item < this.minDurate || item > this.maxDurate
})
// 判断视频分辨率
let raidoBolean = this.videoRatio.find((item) => {
return item.w < this.minW || item.w > this.maxW
if(this.minW < item.w && item.w > this.maxW) {
return item.h < this.minH || item.w > this.maxH
}
})
if(sizeBolean) return this.$message.error('视频只能上传0.5M ~ 50M')
if(durationBolean) return this.$message.error('视频时长只能上传1 ~ 10分钟')
if(raidoBolean) return this.$message.error('视频分辨率不合适')
this.disabled = true
this.submitFile()
},
// 提交到oss服务器
submitFile(){
this.startLoading()
const len = this.file.length
let uploadLength = 0
for (let i = 0; i < len; i++) {
let file = this.file[i];
let headerInfo = this.random_string(6) + '_' + new Date().getTime() + '.' + file.name.split('.').pop();
let storeAs = this.getDate() + headerInfo
this.client.multipartUpload(storeAs, file, {
// 特别说明,这个地方需要设置,不然视频无法用浏览器的方式下载,只能播放。
headers: { 'Content-Disposition': headerInfo }
}).then((res) => {
uploadLength++
if (uploadLength === len) {
this.endLoading()
this.$message({message: `您成功上传了${len}文件`,type: 'success'});
// 上传成功的后得到阿里云 文件路径, 回调保存到自己服务器中,为下载或者在线播放做下一步操作
this.$emit('uploadDone', this.fileInfo);
}
this.fileInfo.push(res.name)
}).catch((err) => {
this.endLoading()
this.$message.error('网络错误,请稍后再试试!')
console.log(err);
});
}
}
}
};
</script>
<style lang="scss" scoped>
#upload-cp{
display: flex;
flex-direction: row;
align-items: center;
.file {
position: relative;
display: inline-block;
background: #D0EEFF;
border: 1px solid #99D3F5;
border-radius: 4px;
padding: 0px 12px;
overflow: hidden;
color: #1E88C7;
text-decoration: none;
text-indent: 0;
font-size: 16px;
}
.file input {
position: absolute;
font-size: 16px;
right: 0;
top: 0;
opacity: 0;
height: 40px;
}
.file:hover {
background: #AADFFD;
border-color: #78C3F3;
color: #004974;
text-decoration: none;
}
p{
font-size: 14px;
margin-left: 10px;
span{
color:red;
}
}
.uploadBtn{
margin-left: 50px;
}
}
</style>
说明:因为采用的是原生的input type=file方式,进而对样式进行了优化。可根据自己需要进行调整。