使用腾讯云对象云存储进行上传文件(Java临时秘钥)
使用已经在腾讯云DNS解析下的域名
测试访问图片(已经上传了的…)
使用Java SDK(多适用于Java开发桌面应用)
注意: Java SDK 大部分都是File对象操作, 不要想着用传给Java服务端再传给COS, 压力过大, 有失COS的初衷,且还有javascript SDK、小程序 SDK, 干嘛费那么大的劲去给服务端增压呢?
- 需要:API密匙、bucketName信息、url信息(域名/默认提供的)
API密匙https://console.cloud.tencent.com/cam/capi
😒我是封装完自己的Utils才意识到,这不纯纯服务端增压工具类吗?
- 如果你想传递文件并记录, js sdk or 小程序 sdk调用api + java后台api数据库字段记录
所以, 如果你是桌面app,直接参考Java SDK 即可, 很简单。c + v就好
使用java获取临时秘钥(主要内容)
如果你懒且不怕永久秘钥泄露, 可以直接找对应的SDK上手即可
- 1-2 小程序 || app || web => 我们的Java服务端 => 腾讯的CAM权限系统与我们的COS临时秘钥同步
- 3-4 CAM => java服务端 => 小程序 || … (拿到临时秘钥)
- 5 携带临时秘钥请求上传、下载操作…
使用小程序SDK
- npm安装 / npm构建小程序有问题的, 我也有小程序构建问题,最笨的方法就是下载
wx-cos-sdk-v5.js 然后引入即可
npm install cos-wx-sdk-v5
const COS = require('cos-wx-sdk-v5');
因为我还没有将后台上传到服务器, 都在本地测试, 所以这里可以省略, 后期配置即可
设置: 微信开发者工具 -> 右上角详细 -> 本地设置 -> ?不校验合法域名…以及HTTPS证书
官方方法一(推荐):后端通过获取临时密钥给到前端,前端计算签名
QCloundController.java
TreeMap<String, Object> config = new TreeMap<String, Object>();
Response credential = null;
try {
config.put("SecretId", cosProperties.getSecretId());
config.put("SecretKey", cosProperties.getSecretKey());
config.put("durationSeconds", 1800);
config.put("bucket", cosProperties.getBucketName());
config.put("region", cosProperties.getRegion());
config.put("allowPrefixes", new String[] {
cosProperties.getAvatarPrefix()
});
config.put("allowActions", new String[] {
"name/cos:PutObject",
"name/cos:PostObject",
"name/cos:GetBucket",
"name/cos:InitiateMultipartUpload",
"name/cos:ListMultipartUploads",
"name/cos:ListParts",
"name/cos:UploadPart",
"name/cos:CompleteMultipartUpload"
});
credential = CosStsClient.getCredential(config);
} catch (Exception e) {
e.printStackTrace();
throw new IllegalArgumentException("no valid secret !");
}
return Result.success(credential);
allowPrefixes 对应 policy的resource(原本是allowPrefix, 从源码中可以得出)
allowActions 对应policy的action
policy更多了解:https://cloud.tencent.com/document/product/436/31923
2. 写完java后台就该写前端小程序了
cos.ts
const COS = require('cos-wx-sdk-v5');
var cos = new COS({
getAuthorization: function (options: any, callback: any) {
console.log(options);
wx.request({
url: 'http://127.0.0.1:8080/qc/key',
data: {
},
dataType: 'json',
success: function (result: any) {
var data = result.data.data;
console.log(data);
var credentials = data && data.credentials;
if (!data || !credentials) return console.error('credentials invalid');
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
StartTime: data.startTime,
ExpiredTime: data.expiredTime,
});
}
});
}
});
export {
cos
}
app.ts :app文件
import { cos } from './COS/cos';
App<IAppOption>({
globalData: {
},
onLaunch() {
cos.getBucket({
Bucket: 'myblogspringboot-1300326898',
Region: 'ap-nanjing',
Prefix: 'avatar/',
}, function (err: any, data: any) {
if (err) {
console.log(err);
return;
}
console.log(data, 2);
});
},
})
官方方法二(不推荐上线,推荐测试):纯前端,简单
cos.ts
const COS = require('cos-wx-sdk-v5');
var cos = new COS({
SecretId: 'AKIDxxxxxxxxxxxxxxxxxxxxxx',
SecretKey: '0mJbdT6UdWBbmjRu75pKbeT4QXP1PYS7'
});
export {
cos
}
永久秘钥获取方式:https://console.cloud.tencent.com/cam/capi
app.ts :还是一样的
import { cos } from './COS/cos';
App<IAppOption>({
globalData: {
},
onLaunch() {
cos.getBucket({
Bucket: 'myblogspringboot-1300326898',
Region: 'ap-nanjing',
Prefix: 'avatar/',
}, function (err: any, data: any) {
if (err) {
console.log(err);
return;
}
console.log(data, 2);
});
},
})
将这种重要的秘钥放在前端肯定不安全, 所以官方推荐方法一
小程序SDK简单使用及封装
utils.ts : 自己的工具类
class Utils {
static uuid() {
return 'xxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
static dateFormat(fmt: string, date: Date) {
date instanceof Date ? '' : date = new Date(date);
let ret;
const opt: any = {
"Y+": date.getFullYear().toString(),
"m+": (date.getMonth() + 1).toString(),
"d+": date.getDate().toString(),
"H+": date.getHours().toString(),
"M+": date.getMinutes().toString(),
"S+": date.getSeconds().toString()
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1)
?
(opt[k])
:
(opt[k].padStart(ret[1].length, "0")));
};
};
return fmt;
}
static randomFileName(filename: String): string {
const separator: string = '.';
const fileNameArr: Array<string> = filename.split(separator);
return fileNameArr[0] + '_' + this.uuid() + '.' + fileNameArr[1];
}
}
export {
Utils
}
cos.ts :cos的封装
const COS = require('cos-wx-sdk-v5');
import { Utils } from '../utils/util';
import { UploadFilesArgOP } from '../interface/index';
class MyCOS {
public AVATAR_PREFIEX: string = 'avatar/';
public BASE_COS_JAVA_KEY_SERVER: string = 'http://127.0.0.1:8080/qc/key';
public BUCKET: string = 'myblogspringboot-1300326898';
public REGION: string = 'ap-nanjing';
public cos: any;
public getBucket(): any {
return new Promise((resolve: any): void => {
this.cos.getBucket({
Bucket: this.BUCKET,
Region: this.REGION,
Prefix: 'avatar/',
}, function (err: any, data: any) {
err ? resolve(err) : '';
resolve(data.Contents);
});
})
}
public simpleUpload(f: WechatMiniprogram.ChooseFile, progress: Function): any{
return new Promise((resolve: (value: unknown) => void) => {
this.cos.postObject({
Bucket: this.BUCKET,
Region: this.REGION,
Key: this.AVATAR_PREFIEX + Utils.randomFileName(f.name),
FilePath: f.path,
onProgress: function (progressData: any) {
progress(progressData);
}
}, function (err: any, data: any) {
resolve(err || data);
});
});
}
uploadFile(key: string, path: string, taskReady?: Function, progress?: Function, fileFinish?: Function): object {
return new Promise(resolve => {
this.cos.uploadFile({
Bucket: this.BUCKET,
Region: this.REGION,
Key: key,
FilePath: path,
SliceSize: 1024 * 1024 * 20,
onTaskReady: function (taskId: number) {
taskReady ? taskReady(taskId) : '';
},
onProgress: function ({ loaded, total, speed }: { loaded: number, total: number, speed: number }) {
progress ? progress(loaded, total, speed) : '';
},
onFileFinish: function (err: any, data: any, options: any) {
fileFinish ? fileFinish(err, data, options) : '';
},
}, function (err: any, data: any) {
err ? resolve(err) : resolve(data);
});
});
}
uploadMoreFile(files: WechatMiniprogram.ChooseFile[], taskReady?: Function, progress?: Function, fileFinish?: Function) {
const uploadFiles: UploadFilesArgOP[] = files.
map((item: WechatMiniprogram.ChooseFile) => {
return Object.assign(item, {
FilePath: item.path,
FileSize: item.size,
Bucket: this.BUCKET,
Region: this.REGION,
Key: this.AVATAR_PREFIEX + Utils.randomFileName(item.name),
onTaskReady(taskId: number) {
taskReady ? taskReady(taskId) : '';
}
})
});
return new Promise((resolve: (value: unknown) => void) => {
this.cos.uploadFiles({
files: uploadFiles,
SliceSize: 1024 * 1024 * 10,
onProgress: (info: any) => {
console.log(info);
progress ? progress(info.total, info.speed, info.percent) : '';
},
onFileFinish: (err: any, data: any, options: any) => {
fileFinish ? fileFinish(err || data, options) : '';
},
}, function (err: any, data: any) {
resolve(err || data);
});
})
}
allTasks(): Array<any> {
return this.cos.getTaskList();
}
clearTask(taskId: string) {
return this.cos.cancelTask(taskId);
}
pauseTask(taskId: string) {
this.cos.pauseTask(taskId);
}
reStartTask(taskId: string) {
this.cos.restartTask(taskId);
}
}
const myCos: MyCOS = new MyCOS();
myCos.cos = new COS({
getAuthorization: function (options: any, callback: any) {
wx.request({
url: myCos.BASE_COS_JAVA_KEY_SERVER,
data: {},
dataType: 'json',
success: function (result: any) {
var data = result.data.data;
var credentials = data && data.credentials;
if (!data || !credentials) return console.error('凭证无效...');
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
StartTime: data.startTime,
ExpiredTime: data.expiredTime,
});
}
});
}
})
export default myCos;
码云地址:https://gitee.com/JYbill/cos_wx_sdk-demo
Github地址:https://github.com/JYbill/cos_wx_sdk-demo
场景:上传3M的图片,点击取消、暂停,过了几秒后腾讯云对象存储COS控制台任然有上传成功的图片。不存在传输速度过快的原因,5M的图片也一样。
|