使用 vue + php 实现
实现思路
后端生成临时秘钥 , 前端通过接口获取临时秘钥上传
php composer.json 增加sdk
"require": {
"qcloud_sts/qcloud-sts-sdk": "3.0.*"
}
php 生成临时签名方法
public function getCosTemporarilyInfo(){
$bucket = env("Tencent.COSBucketName");
$region = env("Tencent.Region"); // cos存储 所在园区
$cacheTime = 1800; // 根据自己的需要 设置缓存时间
$sts = new Sts(); // 安装 腾讯cos 临时签名 sdk
$config = [
'secretId' => env('Tencent.TENCENTCLOUD_SECRET_ID'),
'secretKey' => env('Tencent.TENCENTCLOUD_SECRET_KEY'),
'bucket' => $bucket,
'region' => $region, // bucket 所在园区
'durationSeconds' => $cacheTime, // 密钥有效期
'allowPrefix' => ['myapp/*'], // 这里改成允许的路径前缀,可以根据自己网站的用户登录态判断允许上传的具体路径,例子: a.jpg 或者 a/* 或者 * (使用通配符*存在重大安全风险, 请谨慎评估使用)
// 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
'allowActions' => [
// 简单上传
"name/cos:PutObject",
'name/cos:PostObject',
// 分片上传
'name/cos:InitiateMultipartUpload',
'name/cos:ListMultipartUploads',
'name/cos:ListParts',
'name/cos:UploadPart',
'name/cos:CompleteMultipartUpload'
]
];
// 获取临时密钥,计算签名
return $sts->getTempKeys($config);
}
前端实现: 例如新建一个 utils/cos.js,项目内全局使用:
import COS from 'cos-js-sdk-v5';
const cos = new COS({
// 其他配置项可参考下方 初始化配置项
// getAuthorization 必选参数
getAuthorization: function (options, callback) {
// 初始化时不会调用,只有调用 cos 方法(例如 cos.putObject)时才会进入
// 异步获取临时密钥
// 服务端 JS 示例:https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/
// 服务端其他语言参考 COS STS SDK :https://github.com/tencentyun/qcloud-cos-sts-sdk
// STS 详细文档指引看:https://cloud.tencent.com/document/product/436/14048
const stsUrl = 'http://example.com/server/sts'; // stsUrl 替换成您自己的后端服务
fetch(stsUrl)
.then(response => response.json())
.then(data => {
if (!data || !data.credentials) {
return console.error('credentials invalid:\n' + JSON.stringify(data, null, 2))
}
// 检查credentials格式
const { credentials } = data;
console.log(credentials);
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
SecurityToken: credentials.sessionToken,
// 建议返回服务器时间作为签名的开始时间,避免客户端本地时间偏差过大导致签名错误
StartTime: data.startTime, // 时间戳,单位秒,如:1580000000
ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000000
ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
});
})
.catch(error => {
console.error('获取临时密钥失败', error);
});
}
});
export default cos;
页面使用-单文件
import cos from 'utils/cos';
let taskId;
// 上传文件,file为选择的文件
async function upload(file) {
try {
const data = await cos.uploadFile({
Bucket: 'examplebucket-1250000000', // 填写自己的 bucket,必须字段
Region: 'COS_REGION', // 存储桶所在地域,必须字段
Key: '1.jpg', // 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段
Body: file, // 上传文件对象
SliceSize: 1024 * 1024 * 5, // 触发分块上传的阈值,超过5MB 使用分块上传,小于5MB使用简单上传。可自行设置,非必须
onProgress: function(progressData) {
console.log('上传进度:', progressData);
},
onTaskReady: function(id) { // 非必须
taskId = id;
},
});
console.log('上传成功', data);
} catch (e) {
console.error('上传失败', e);
}
}
// 监听上传队列
cos.on('update-list', data => {
console.log(data);
});
// 暂停上传任务
cos.pauseTask(taskId);
// 重启上传任务
cos.restartTask(taskId);
// 取消上传任务
cos.cancelTask(taskId)
页面使用-多文件
let arrFileList = []
for(let i = 0;i<this.fileData.length;i++){
let extension = this.fileData[i].name.lastIndexOf('.')
extension = extension !== -1 ? this.fileData[i].name.substring(extension + 1) : '';
let uniqueKey = this.generateUniqueKey();
let key = 'myapp/'+ this.type + '/' + this.getYmd() + '/' + uniqueKey +'.' + extension;
// key = 'myapp/image/' + (i+1) +'.'+extension;
let fileInfo = {
Bucket: this.Bucket, // 填入您自己的存储桶,必须字段
Region: this.Region, // 存储桶所在地域,例如ap-beijing,必须字段
Key: key, // 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段
Body: this.fileData[i], // 必须,上传文件对象,可以是input[type="file"]标签选择本地文件后得到的file对象
file_mime:this.fileData[i].type,
title:this.fileData[i].name,
type:this.typeMap[this.type],
onTaskReady: function(uniqueKey) {
// taskId可通过队列操作来取消上传cos.cancelTask(taskId)、停止上传cos.pauseTask(taskId)、重新开始上传cos.restartTask(taskId)
console.log(uniqueKey);
},
};
arrFileList.push(fileInfo);
}
//批量上传文件
cos.uploadFiles({
files: arrFileList,
SliceSize: 1024 * 1024 * 10, // 设置大于10MB采用分块上传
}, function (err, data) {
if(data.files.length >0){
for(let i=0;i<data.files.length;i++){
if(data.files[i].data){
let file = {
'title':data.files[i].options.title,
'file_id':'',
'file_url':'https://'+data.files[i].data.Location,
'file_mime':data.files[i].options.file_mime,
'type':data.files[i].options.type
};
succ_files.push(file);
}
}
}
if(succ_files.length >0){
batchAdd({file_arr:succ_files}).then((res) => {
if (res.code == 200) {
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
}else{
this.$message.error('上传失败请稍后重试')
}
});