使用vue 结合 腾讯cos实现上传
上传图片或者文档或者视频,方法都是一样的,区别在于判断上传的文件格式不同
eg. 上传图片可以上传的格式有 : [‘.jpg’, ‘.gif’, ‘.jpeg’, ‘.bmp’, ‘.png’]
cos
cos客户端:https://cloud.tencent.com/document/product/436/11366
- 可以在客户端看到上传成功后的文件
*注意:上传大文件要使用分块上传
简单上传接口适用于小文件上传,大文件请使用分块上传接口,详情请参见 cos对象操作 文档
js代码
安装依赖包
1
npm install cos-js-sdk-v5
使用 axios 来请求接口
- 代码 封装 cos.js 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149import CosCloud from "cos-js-sdk-v5"
import axios from 'axios'
// 上传文件(调用相关api putObject来上传文件)
/**
* @method uploadFile
* @param {object} cos
*/
function uploadFile(cos, file, signInfo, callback) {
// name: 图片的名称,可以自定义,这里为了不覆盖相同名照片,使用了时间戳
// /store/st 这个是文件要上传到的cos下的目录
let name = `/store/st/${new Date().valueOf()}`
let pic = ''
// Bucket: 存储桶 Bucket 的名称,命名规则为 BucketName-APPID,此处填写的存储桶名称必须为此格式
// Region:Bucket 所在地域,枚举值请参阅 地域和访问域名:https://cloud.tencent.com/document/product/436/6224
// 以下有一个小文件上传,一个大文件上传, 只用其中一个即可,如果有大文件上传就用分块上传
// 上传小文件使用
cos.putObject(
{
Bucket: 'marryparty-1253457213',
Region: 'ap-guangzhou',
Key: `${name}`,
Dir: 'store',
Body: file,
onHashProgress: function (progressData) {
console.log('校验中', JSON.stringify(progressData));
},
onProgress: function (progressData) {
console.log('上传中', progressData)
if (progressData.percent === 1) {
// 上传完执行操作 这里将图片的 pic 作为图片的src 抛出去,在调用的地方用res.pic获取即可
pic = `http://marryparty-1253457213.cos.ap-guangzhou.myqcloud.com${name}`
}
},
},
function (err, data) {
console.log(data)
if (err) {
callback({ success: false, msg: '文件上传失败!' });
return;
}
// 上传成功把数据抛出去, pic 是上文的图片的链接
callback({ success: true, msg: '上传成功!', data: data, signInfo: signInfo, pic: pic });
}
)
// 上传大文件使用分块上传
cos.sliceUploadFile({
Bucket: 'trace-1254950508',
Region: 'ap-guangzhou',
Key: `${name}`,
Body: file,
onProgress: function (progressData) {
if (progressData.percent === 1) {
// 上传完执行操作 这里将图片的 video 作为视频的src 抛出去,在调用的地方用res.video获取即可
// 这里的链接是cos的路径 + 文件名字
video = `https://trace-1254950508.cos.ap-guangzhou.myqcloud.com/${name}`
}
}
}, function (err, data) {
console.log(err, data)
if (err) {
callback({ success: false, msg: '文件上传失败!' })
return
}
// 上传成功把数据抛出去, video 是上文的视频的链接
callback({ success: true, msg: '上传成功!', data: data, signInfo: signInfo, video: video })
})
}
// 获取文件上传密钥(最好存在后端通过ajax请求获取,安全性较高)
function getFileToken(Vue, fileInfo, cos, file, uploadStatusCallbalck) {
// 秘钥是请求后台的接口,替换即可
// 正式环境会自动加域名
let url = '/manage/store-api/get_ticket'
// 本地
// let url = 'https://store.ihuyue.cn/manage/store-api/get_ticket'
if (!file) return;
// 异步获取临时密钥
axios
.get(url)
.then(function (res) {
if (res.data.ret == 0) {
//获取的临时秘钥存储在vuex中
Vue.$store.commit('setUPDATEFILEINFO', res.data.data);
uploadFile(cos, file, res.data.data, uploadStatusCallbalck);
} else {
uploadStatusCallbalck({ success: false, msg: '获取文件秘钥失败!' });
}
})
.catch(function (err) {
uploadStatusCallbalck({ success: false, msg: '获取文件秘钥接口出错!' });
});
}
/**
* 初始化上传文件对象
* @param {object} Vue
* @param {string} fileName 文件名
* @param {object} file 上传的文件流及文件类型 名称相关信息
* @param {Array} 允许上传的文件类型
* @param {function} uploadStatusCallbalck
* @return {function} 返回回调函数
*/
export const initUploadObj = function (Vue, fileName, file, type, uploadStatusCallbalck) {
let fileInfo = {
file_name: fileName,
media_type: 2,
media_sub_type: 0,
size_of_bytes: 122,
file_expired_type: 'permanent',
};
console.log(file, 'file---------')
// 上传图片大小做限制
if (file.size > 2048) {
Vue.$Message.error('请上传小于2M的图片!')
return
}
//前端做文件类型限制 (使用的就是调用里的type)
if (type == 'image') {
type = ['.jpg', '.gif', '.jpeg', '.bmp', '.png']
}
if (type == 'excel') {
type = ['.xlsx']
}
if (type == 'video') {
type = ['.mp4']
}
let fileType = file.name ? file.name.substring(file.name.lastIndexOf(".")).toLowerCase() : '';
if (!!type && type.indexOf(fileType) < 0) {
uploadStatusCallbalck({ success: false, msg: '请上传正确的' + type + '文件格式!' })
return
}
var cos = new CosCloud({
getAuthorization: function (options, callback) {
let singleInfo = Vue.$store.state.app.fileToken;
callback({
TmpSecretId: singleInfo.credentials.tmpSecretId,
TmpSecretKey: singleInfo.credentials.tmpSecretKey,
XCosSecurityToken: singleInfo.credentials.sessionToken,
ExpiredTime: singleInfo.expiredTime,
});
},
});
fileInfo.file_name = file.name
//获取文件上传密钥
getFileToken(Vue, fileInfo, cos, file, uploadStatusCallbalck);
}
export default initUploadObj
使用
html 这里只上传一张图片,可以根据自己需要修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14<div class="l-pic">
<div v-if="formValidate.header" class="upload-img">
<img class="up-img" :src="formValidate.header">
<div class="up-change">
<div>修改头像</div>
<input class="up-input" type="file" id="file" @change="uploadImg()" />
</div>
</div>
<div v-else class="up-block">
<Icon type="ios-add" size="25" />
<input class="up-input" type="file" id="file" @change="uploadImg()" />
</div>
<div class="msg">上传图片的宽高比必须满足1:1,否则无法上传!建议图片尺寸为130 * 130。(最大不超过2M)</div>
</div>这里把css也贴出来,方便看效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56.l-pic {
width: 100%;
display: flex;
.upload-img {
position: relative;
height: 100px;
.up-img {
width: 100px;
height: 100px;
}
.up-change {
position: absolute;
bottom: 0;
left: 0;
width: 100px;
height: 20px;
line-height: 20px;
text-align: center;
color: #fff;
background: rgba(0, 0, 0, .4);
.up-input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
outline: none;
opacity: 0;
z-index: 3;
}
}
}
.up-block {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
border: 1px dashed #ccc;
.up-input {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
outline: none;
opacity: 0;
z-index: 3;
}
}
.msg {
color: rgb(45, 140, 240);
margin-left: 10px;
}
}js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35import initUploadObj from '@/libs/cos'
uploadImg() {
let that = this
let file = document.querySelector('input[type=file]').files[0]
//初始化文件上传
let type = 'image'
// 上传文件时只有 type 需要改,可以自定义(在js里会用到这个值判断上传的文件格式是否正确)
// 上传图片 是'image' initUploadObj(that, file.name, file, 'image', function(res) {}
// 上传视频 是'video' initUploadObj(that, file.name, file, 'video', function(res) {}
initUploadObj(that, file.name, file, type, function(res) {
if (res.success) {
// 这里res是cos里返回的数据
console.log(res.pic)
// 上传图片比例限制
let img = new Image()
img.src = res.pic
img.onload = function(){
let w = img.width
let h = img.height
if (w != h) {
that.$Message.error('请按照规定的宽高比上传图片!')
return
} else {
that.formValidate.header = res.pic
that.formValidate = JSON.parse(JSON.stringify(that.formValidate))
}
}
} else {
this.$Message.error('图片上传失败')
}
})
},