对象存储(Cloud Object Storage,COS)是腾讯云提供的一种存储海量文件的分布式存储服务,具有高扩展性、低成本、可靠安全等优点。通过控制台、API、SDK 和工具等多样化方式,用户可简单、快速地接入 COS,进行任意格式文件的上传、下载和管理,实现海量数据存储和管理。同时遍布全国范围的 CDN/EdgeOne 节点可以对文件下载进行加速。
前几天,我们分享了关于服务器端腾讯云-对象存储服务(COS)的使用总结为了安全起见,配置放在服务器端,通过服务器端生成临时密钥供客户端使用,一般在30分钟左右的有效时长,可以看出,服务器端只是起到一个配角作用,今天,我们主要讲一下主角对对象存储服务的API调用,也就是图片中的1,4,5的操作。
package.json里添加如下的库
"dependencies": {
"cos-js-sdk-v5": "^1.4.20"
}
我们书写工具类upFile.js,包含了上传图片和视频到腾讯云COS的功能
import modal from '@/utils/modal.js';
import request from '@/utils/request';
import COS from 'cos-js-sdk-v5';
const cosSessionKey = 'cos_session'
/**获取cos临时密钥等信息*/
function getCosInfo() {
return new Promise((resolve, rejct) => {
request({
url: '/system/cos/get',
method: 'get',
}).then(res => {
var data = res.data
if (data) {
uni.setStorageSync(cosSessionKey, data);
resolve(data);
}
})
})
}
var cos = new COS({
SimpleUploadMethod: 'putObject',
getAuthorization: function(options, callback) {
var cosData = uni.getStorageSync(cosSessionKey);
callback({
TmpSecretId: cosData.secretId,
TmpSecretKey: cosData.secretKey,
// v1.2.0之前版本的 SDK 使用 XCosSecurityToken 而不是 SecurityToken
SecurityToken: cosData.sessionToken,
// 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
StartTime: cosData.startTime, // 时间戳,单位秒,如:1580000000
ExpiredTime: cosData.expiredTime, // 时间戳,单位秒,如:1580000900
});
}
});
// 上传文件到腾讯云
const cosUpLoadFile = async (params) => {
let uploadFile = '';
await uniChooseImage().then(res => {
uploadFile = res
})
return cosUploadFile(uploadFile, params);
};
// 选择图片
const uniChooseImage = () => {
return new Promise((resolve, rejct) => {
uni.chooseImage({
// 从本地相册选择图片或使用相机拍照。
count: 1, //默认选择1张图片
sizeType: ['original', 'compressed'], //original 原图,compressed 压缩图,默认二者都有
success: res1 => {
resolve(res1.tempFiles[0]);
}
});
});
}
const cosUploadFile = async (file, params) => {
var cosData = uni.getStorageSync(cosSessionKey);
if (!cosData || !cosData.bucket) { //如果cos信息不存在
//等待获取到cosData
await getCosInfo().then(res => {
cosData = res
});
}
let promise = new Promise((resolve, rejct) => {
modal.loading("上传中...")
cos.uploadFile({
/* 填入您自己的存储桶,必须字段 */
Bucket: cosData.bucket,
/* 存储桶所在地域,例如ap-beijing,必须字段 */
Region: cosData.region,
/* 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段 */
Key: params.uploadKey,
/* 必须,上传文件对象,可以是input[type="file"]标签选择本地文件后得到的file对象 */
Body: file,
/* 触发分块上传的阈值,超过5MB使用分块上传,非必须 */
SliceSize: 1024 * 1024 * 5,
onTaskReady: function(taskId) {
/* 非必须 */
console.log(taskId);
},
onProgress: function(progressData) {
/* 非必须 */
console.log(JSON.stringify(progressData));
},
onFileFinish: function(err, data, options) {
/* 非必须 */
console.log(options.Key + '上传' + (err ? '失败' : '完成'));
},
// 支持自定义headers 非必须
Headers: {
'x-cos-meta-test': 123
},
}, function(err, data) {
if (data && data.statusCode == 200) {
let datas = {
imgUrl: 'https://' + data.Location,
imgKey: params.uploadKey
}
resolve(datas);
} else if (err && err.statusCode == 403) {
if ("Request has expired" == err.message) {
console.log("失效Request has expired!重新获取cos信息");
uni.removeStorageSync(cosSessionKey);
cosUploadFile(file, params).then(res => {
resolve(res);
});
}
} else {
modal.msg(err ? err.message : "上传失败!");
}
uni.hideLoading();
});
});
return promise;
}
const cosDeleteFile = async (params) => {
var cosData = uni.getStorageSync(cosSessionKey);
if (!cosData || !cosData.bucket) { //如果cos信息不存在
//等待获取到cosData
await getCosInfo().then(res => {
cosData = res
});
}
console.log(params.uploadKey);
cos.deleteObject({
/* 填入您自己的存储桶,必须字段 */
Bucket: cosData.bucket,
/* 存储桶所在地域,例如ap-beijing,必须字段 */
Region: cosData.region,
Key: params.uploadKey,
}, function(err, data) {
console.log("deleteObject");
console.log(err || data);
if (err && err.statusCode == 403) {
if ("Request has expired" == err.message) {
console.log("失效Request has expired!重新获取cos信息");
uni.removeStorageSync(cosSessionKey);
cosDeleteFile(params);
}
}
});
}
export default {
cosUpLoadFile,
cosDeleteFile
}
先发起上传图片请求,看下本地有没有临时密钥,如果没有则,通过发送请求https://*****.com/system/cos/get从服务器获取,获取结果如下:
{
"code": 200,
"msg": "处理成功",
"time": 1693467116217,
"data": {
"bucket": "gamioo2010-12********2",
"region": "ap-shanghai",
"secretId": "AKIDdPg4NmRr****************************************EXdXdkWNIn2z",
"secretKey": "g7drx*********************************tiW5EM=",
"sessionToken": "EJn8gbXdS6r579C9RTOaGmR22S**************************FFB6uFy61jg",
"startTime": 1693467116,
"expiredTime": 1693467176
}
}
然后把这份临时密钥数据存到local Storage, 供后续的cos 存/取/删除对象使用,直到使用COS服务返回Request has expired 错误码后,那么再次通过/system/cos/get请求向服务器获取一次临时密钥,
具体使用,身份证图片上传:
import upFile from '@/utils/upFile.js';
uploadKey(imgName) {
return "idCard/" + this.userInfo.id + '/' + imgName + '.jpg';
},
uploadIdImg(imgName) {
upFile.cosUpLoadFile({
uploadKey: this.uploadKey(imgName),
}).then(res => {
console.log(res);
if ('front' == imgName) {
this.formData.front = res.imgUrl;
} else {
this.formData.back = res.imgUrl;
}
})
},
那么,如何往cos服务存对象的呢?
本质发了个put 的URL请求,这串url 的组成规则实际上为 https://[bucket].[region].myqcloud.com/{key}
例如:
https://gamioo2010-1***********.cos.ap-shanghai.myqcloud.com/idCard/11/back.jpg
正常情况下,会返回对象的存储地址,接下去就可以做后续的逻辑处理:
{
"imgUrl": "https://gamioo2010-***********.cos.ap-shanghai.myqcloud.com/idCard/11/front.jpg",
"imgKey": "idCard/11/front.jpg"
}
如果返回Request has expired,
PUT https://gamioo2010-***********.cos.ap-shanghai.myqcloud.com/idCard/11/back.jpg 403 (Forbidden)
{"loaded":130736,"total":130736,"speed":274079.66,"percent":1}
cos,postobject-err] AccessDenied: Request has expired
at http://localhost:3200/node modules/.vite/deps/cos-js-sdk-v5.js?v=b340976d:9468:31
at xhr.onload (htto://1ocalost:3200/node modules/vite/dens/cos-s-Sdk-V5.1S?V-b340976d:2469:15
则重新发起获取临时密钥的请求,直到完成该过程。
本文主要列举了客户端在拿到临时密钥后,如何进行后续的COS操作,本文暂时只举例了存储的操作,至于其他的COS接口调用,调用方法类似,我们不再赘述。