之前公司使用的百度云BOS上传,当时也查了不少资料,但是没整理发布o(╥﹏╥)o,由于不知名原因,现在要换成COS,于是又开始了一波查文档敲代码的过程
一、COS官方文档
1. 安装&引入
npm i cos-js-sdk-v5 --save
import COS from 'cos-js-sdk-v5';
2. 使用
<input type="file" value="选择文件" ref="fileUpload" @change="uploadFile" />
getCos() {
this.cosClient = new COS({
getAuthorization: (options, callback) => {
// 异步获取临时密钥
this.$fetch({
url: '/xxx/api/getxxxkey',
method: 'get',
}).then((res) => {
if (res && res.errNo === 0) {
const { data } = res;
callback({
TmpSecretId: data.tmpSecretId,
TmpSecretKey: data.tmpSecretKey,
XCosSecurityToken: data.sessionToken,
StartTime: data.StartTime,
ExpiredTime: data.ExpiredTime,
});
}
}).catch(() => {
this.loading = false;
});
},
});
},
uploadFile(e) {
const file = e.target.files[0];
Promise
.all([this.getCos()]) // 获取文件的md5
.then((md5) => {
const fileName = md5[0];
const name = file.name.replace(/.*\.(.*)|(.*)/, (all, ext) => `${fileName}.${ext || all}`);
const date = this.dateStr(); // 获取上传日期,例:20200108
this.bucketPath = `xaj/test/${date}/${name}`; // Key: 对象键(Object 的名称),对象在存储桶中的唯一标识
this.putObject([this.bucketPath, file]);
});
},
putObject([key, file]) {
// 简单上传文件
this.cosClient.putObject({
Bucket: 'test-124545', // 存储桶名称,必须;Bucket 格式:test-1250000000
Region: 'ap-beijing', // 存储桶所在地域, 必须
Key: key, /* 必须 */
StorageClass: 'STANDARD',
Body: file, // 上传文件对象
}, (err, data) => {
if (err) {
this.$message.error(err);
} else {
this.$message.success('文件上传成功~');
// 获取url
const url = this.cosClient.getObjectUrl({
Bucket: 'test-124545',
Region: 'ap-beijing',
Key: key,
});
console.log(url); // 有效可访问url生成
}
});
},
官方文档中简单文件上传快速入口, 官方文档中获取签名url快速入口。
3. 临时密钥
由于密钥放在前端会显示 SecretId 和 SecretKey,我们把永久密钥过程放在后端,前端通过 ajax 向后端获取一个临时密钥,正式部署时请再后端加一层您网站本身的权限检验。
// 初始化实例
var cos = new COS({
getAuthorization: function (options, callback) {
// 异步获取临时密钥
$.get('http://example.com/server/sts.php', {
bucket: options.Bucket,
region: options.Region,
}, function (data) {
var credentials = data.credentials;
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
// 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
StartTime: data.startTime, // 单位是秒
ExpiredTime: data.expiredTime
});
});
}
});
callback
释义:客户端请求COS
,出于安全考虑使用的密钥要受到policy的约束,callback
就是得到server
端返回的 临时账号信息,包括
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
StartTime: data.startTime, // 时间戳,单位秒,如:1580000000
ExpiredTime: data.expiredTime,
客户端再用临时账号密钥和token
对COS
发起请求。
4. 踩坑解决
① 按照文档中的方法使用getAuthorization
,并无法正常上传,会提示authorization error
,是因为我在使用时没有给callback
传StartTime
和ExpiredTime
。
② 上传成功后返回的链接无法正常打开,报错Cos Error Code: AccessDenied
,后经过查资料,得知是后端生成临时密钥时,没给getObject
权限,如下$config
最后一行:
$config = [
'url' => URL,
'domain' => DOMAIN,
'proxy' => '',
'secretId' => $conf['secret_id'], // 固定密钥
'secretKey' => $conf['secret_key'], // 固定密钥
'bucket' => $bucket, // 换成你的 bucket
'region' => $region, // 换成 bucket 所在园区
'durationSeconds' => EXPIRE_TIME, // 密钥有效期
'allowPrefix' => '*', // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的目录,例子:* 或者 a/* 或者 a.jpg
// 密钥的权限列表。简单上传和分片需要以下的权限,
'allowActions' => array (
// 简单上传
'name/cos:PutObject',
'name/cos:PostObject',
// 分片上传
'name/cos:InitiateMultipartUpload',
'name/cos:ListMultipartUploads',
'name/cos:ListParts',
'name/cos:UploadPart',
'name/cos:CompleteMultipartUpload',
// 下载
'name/cos:GetObject',
)
];
// 获取临时密钥,计算签名
$tempKeys = $this->sts->getTempKeys($config);
二、如何查看COS的SecretId
、SecretKey
、region
、bucket
1. bucket
/region
2. SecretId
/SecretKey
点击【运API密钥】
【继续使用】
第一次进入时要点击【新建密钥】生成密钥,即可查看。
三、上传文件所在位置
log
2020-03-19:更新临时密钥使用问题解决(踩坑)