Skip to content

Commit de519f9

Browse files
authored
Merge pull request #100 from tencentyun/feat/pictureOperation
feat: 增加 cos.request 接口
2 parents 48653a5 + a437eb6 commit de519f9

File tree

4 files changed

+166
-72
lines changed

4 files changed

+166
-72
lines changed

demo/demo.js

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -793,31 +793,31 @@ function putObject() {
793793
var filename = '1mb.zip';
794794
var filepath = path.resolve(__dirname, filename);
795795
util.createFile(filepath, 1024 * 1024, function (err) {
796-
// 调用方法
797-
cos.putObject({
798-
Bucket: config.Bucket, /* 必须 */
799-
Region: config.Region,
800-
Key: filename, /* 必须 */
801-
onTaskReady: function (tid) {
802-
TaskId = tid;
803-
},
804-
onProgress: function (progressData) {
805-
console.log(JSON.stringify(progressData));
806-
},
807-
// 格式1. 传入文件内容
808-
// Body: fs.readFileSync(filepath),
809-
// 格式2. 传入文件流,必须需要传文件大小
810-
Body: fs.createReadStream(filepath),
811-
ContentLength: fs.statSync(filepath).size,
812-
Headers: {
813-
// 万象持久化接口,上传时持久化
814-
// 'Pic-Operations': '{"is_pic_info": 1, "rules": [{"fileid": "test.jpg", "rule": "imageMogr2/thumbnail/!50p"}]}'
815-
},
816-
}, function (err, data) {
817-
console.log(err || data);
818-
fs.unlinkSync(filepath);
819-
});
820-
});
796+
// 调用方法
797+
cos.putObject({
798+
Bucket: config.Bucket, /* 必须 */
799+
Region: config.Region,
800+
Key: filename, /* 必须 */
801+
onTaskReady: function (tid) {
802+
TaskId = tid;
803+
},
804+
onProgress: function (progressData) {
805+
console.log(JSON.stringify(progressData));
806+
},
807+
// 格式1. 传入文件内容
808+
// Body: fs.readFileSync(filepath),
809+
// 格式2. 传入文件流,必须需要传文件大小
810+
Body: fs.createReadStream(filepath),
811+
ContentLength: fs.statSync(filepath).size,
812+
Headers: {
813+
// 万象持久化接口,上传时持久化
814+
// 'Pic-Operations': '{"is_pic_info": 1, "rules": [{"fileid": "test.jpg", "rule": "imageMogr2/thumbnail/!50p"}]}'
815+
},
816+
}, function (err, data) {
817+
console.log(err || data);
818+
fs.unlinkSync(filepath);
819+
});
820+
});
821821
}
822822

823823
function putObjectCopy() {
@@ -831,14 +831,6 @@ function putObjectCopy() {
831831
});
832832
}
833833

834-
cos.deleteObject({
835-
Bucket: config.Bucket,
836-
Region: config.Region,
837-
Key: 'pingjs/ext2020/qqindex2018/dist/img/qq_logo_2x.png',
838-
}, function (err, data) {
839-
getObject();
840-
});
841-
842834
function getObject() {
843835
var filepath1 = path.resolve(__dirname, '1mb.out1.zip');
844836
var filepath2 = path.resolve(__dirname, '1mb.out2.zip');
@@ -848,14 +840,16 @@ function getObject() {
848840
cos.getObject({
849841
Bucket: config.Bucket,
850842
Region: config.Region,
851-
Key: 'pingjs/ext2020/qqindex2018/dist/img/qq_logo_2x.png',
843+
Key: '1mb.zip',
852844
onProgress: function (progressData) {
853845
console.log(JSON.stringify(progressData));
854846
}
855847
}, function (err, data) {
856-
console.log(err);
857-
console.log(data);
858-
// fs.writeFileSync(filepath1, data.Body);
848+
if(data){
849+
fs.writeFileSync(filepath1, data.Body);
850+
} else {
851+
console.log(err);
852+
}
859853
});
860854

861855
}
@@ -1389,6 +1383,24 @@ function deleteFolder() {
13891383
});
13901384
}
13911385

1386+
function request() {
1387+
// 对云上数据进行图片处理
1388+
var filename = 'exampleImage.png';
1389+
cos.request({
1390+
Bucket: config.Bucket,
1391+
Region: config.Region,
1392+
Key: filename,
1393+
Method: 'POST',
1394+
Action: 'image_process',
1395+
Headers: {
1396+
// 万象持久化接口,上传时持久化
1397+
'Pic-Operations': '{"is_pic_info": 1, "rules": [{"fileid": "desample_photo.jpg", "rule": "imageMogr2/thumbnail/200x/"}]}'
1398+
},
1399+
}, function (err, data) {
1400+
console.log(err || data);
1401+
});
1402+
}
1403+
13921404
// getService();
13931405
// getAuth();
13941406
// getV4Auth();

index.d.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ declare namespace COS {
3434
type Query = Record<string, any>;
3535
/** 请求里的 Header 参数 */
3636
type Headers = Record<string, any>;
37+
/** 请求里的 URL 中对象存储 API 接口名,如 acl、tagging 等 */
38+
type Action = string;
3739
/** 一个字符的分隔符,常用 / 字符,用于对对象键进行分组。所有对象键中从 prefix 或从头(如未指定 prefix)到首个 delimiter 之间相同的部分将作为 CommonPrefixes 下的一个 Prefix 节点。被分组的对象键不再出现在后续对象列表中 */
3840
type Delimiter = '/' | string;
3941
/** 规定返回值的编码方式,可选值:url,代表返回的对象键为 URL 编码(百分号编码)后的值,例如“腾讯云”将被编码为%E8%85%BE%E8%AE%AF%E4%BA%91 */
@@ -169,6 +171,8 @@ declare namespace COS {
169171
UploadIdCacheLimit?: number,
170172
/** 分片上传缓存的 UploadId 列表时,保存的本地缓存文件目录路径,nodejs-sdk 默认 500 个,js-sdk 默认 50 */
171173
ConfCwd?: string,
174+
/** 301/302 回源跟随配置。 */
175+
FollowRedirect?: boolean,
172176
/** 获取签名的回调方法,如果没有 SecretId、SecretKey 时,必选 */
173177
getAuthorization?: (
174178
options: GetAuthorizationOptions,
@@ -1094,8 +1098,10 @@ declare namespace COS {
10941098
BodyType?: 'text' | 'blob' | 'arraybuffer',
10951099
/** 写入流,可以传本地文件写入流 */
10961100
Output?: Stream,
1097-
/** 请求里的 Url Query 参数 */
1101+
/** 请求里的 Url Query 参数,传入该值中的 key/value 将会被 URLEncode */
10981102
Query?: Query,
1103+
/** 请求里的 Url Query 参数。传入该值将直接拼接在 Url 上,不会对其进行 URLEncode */
1104+
QueryString?: string,
10991105
/** 当对象在指定时间后被修改,则返回对象,否则返回 HTTP 状态码为304(Not Modified) */
11001106
IfModifiedSince?: string,
11011107
/** 当对象在指定时间后未被修改,则返回对象,否则返回 HTTP 状态码为412(Precondition Failed) */
@@ -1745,15 +1751,32 @@ Bulk:批量模式,恢复时间为24 - 48小时。 */
17451751
/** 上传任务列表 */
17461752
type TaskList = Task[]
17471753

1754+
// request
1755+
/** request 接口参数 */
1756+
interface RequestParams extends ObjectParams {
1757+
/** 操作方法,如 get,post,delete, head 等 HTTP 方法 */
1758+
Method: string,
1759+
/** 请求里的 Url Query 参数 */
1760+
Query?: Query,
1761+
/** 请求里的 Body 参数 */
1762+
Body?: Body,
1763+
/** 请求的 API 动作接口(可理解为不带 = 的 Query 参数),如 acl、tagging、image_process 等 */
1764+
Action: Action
1765+
}
1766+
/** Request 接口返回值 */
1767+
interface RequestResult extends GeneralResult {}
1768+
17481769
// getObjectUrl
17491770
/** getObjectUrl 接口参数 */
17501771
interface GetObjectUrlParams extends ObjectParams {
17511772
/** 获取的 Url 是否计算签名 */
17521773
Sign?: boolean,
17531774
/** 请求方法 */
17541775
Method?: Method,
1755-
/** 请求里的 Url Query 参数 */
1776+
/** 请求里的 Url Query 参数,传入该值中的 key/value 将会被 URLEncode */
17561777
Query?: Query,
1778+
/** 请求里的 Url Query 参数。传入该值将直接拼接在 Url 上,不会对其进行 URLEncode */
1779+
QueryString?: string,
17571780
/** 签名几秒后失效,默认为900秒 */
17581781
Expires?: number,
17591782
}
@@ -2117,6 +2140,10 @@ declare class COS {
21172140
/** 判断上传队列是否有未完成的任务 */
21182141
isUploadRunning(): boolean;
21192142

2143+
/** 分片复制文件 */
2144+
request(params: COS.RequestParams, callback: (err: COS.CosError, data: COS.RequestResult) => void): void;
2145+
request(params: COS.RequestParams): Promise<COS.RequestResult>;
2146+
21202147
/** 获取文件下载链接 @see https://cloud.tencent.com/document/product/436/35651 */
21212148
getObjectUrl(params: COS.GetObjectUrlParams, callback: (err: COS.CosError, data: COS.GetObjectUrlResult) => void): string;
21222149

sdk/base.js

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,7 @@ function listObjectVersions(params, callback) {
18581858
*/
18591859
function getObject(params, callback) {
18601860
var reqParams = params.Query || {};
1861+
var reqParamsStr = params.QueryString || '';
18611862

18621863
reqParams['response-content-type'] = params['ResponseContentType'];
18631864
reqParams['response-content-language'] = params['ResponseContentLanguage'];
@@ -1933,6 +1934,7 @@ function getObject(params, callback) {
19331934
VersionId: params.VersionId,
19341935
headers: params.Headers,
19351936
qs: reqParams,
1937+
qsStr: reqParamsStr,
19361938
rawBody: true,
19371939
outputStream: outputStream,
19381940
onDownloadProgress: onDownloadProgress,
@@ -2977,6 +2979,36 @@ function multipartAbort(params, callback) {
29772979
});
29782980
}
29792981

2982+
/**
2983+
* cos 内置请求
2984+
* @param {Object} params 参数对象,必须
2985+
* @param {String} params.Bucket Bucket名称,必须
2986+
* @param {String} params.Region 地域名称,必须
2987+
* @param {String} params.Key object名称,必须
2988+
* @param {Function} callback 回调函数,必须
2989+
* @return {Object} err 请求失败的错误,如果请求成功,则为空。https://cloud.tencent.com/document/product/436/7730
2990+
* @return {Object} data 返回的数据
2991+
*/
2992+
function request(params, callback) {
2993+
submitRequest.call(this, {
2994+
method: params.Method,
2995+
Bucket: params.Bucket,
2996+
Region: params.Region,
2997+
Key: params.Key,
2998+
action: params.Action,
2999+
headers: params.Headers,
3000+
qs: params.Query,
3001+
body: params.Body,
3002+
}, function (err, data) {
3003+
if (err) return callback(err);
3004+
if (data && data.body) {
3005+
data.Body = data.body;
3006+
delete data.body;
3007+
}
3008+
callback(err, data);
3009+
});
3010+
}
3011+
29803012
/**
29813013
* 获取签名
29823014
* @param {Object} params 参数对象,必须
@@ -3032,10 +3064,22 @@ function getObjectUrl(params, callback) {
30323064
region: params.Region,
30333065
object: params.Key,
30343066
});
3067+
3068+
var queryParamsStr = '';
3069+
if(params.Query){
3070+
queryParamsStr += util.obj2str(params.Query);
3071+
}
3072+
if(params.QueryString){
3073+
queryParamsStr += (queryParamsStr ? '&' : '') + params.QueryString;
3074+
}
3075+
3076+
var syncUrl = url;
30353077
if (params.Sign !== undefined && !params.Sign) {
3036-
callback(null, {Url: url});
3037-
return url;
3078+
queryParamsStr && (syncUrl += '?' + queryParamsStr);
3079+
callback(null, {Url: syncUrl});
3080+
return syncUrl;
30383081
}
3082+
30393083
var AuthData = getAuthorizationAsync.call(this, {
30403084
Action: ((params.Method || '').toUpperCase() === 'PUT' ? 'name/cos:PutObject' : 'name/cos:GetObject'),
30413085
Bucket: params.Bucket || '',
@@ -3056,16 +3100,18 @@ function getObjectUrl(params, callback) {
30563100
AuthData.ClientIP && (signUrl += '&clientIP=' + AuthData.ClientIP);
30573101
AuthData.ClientUA && (signUrl += '&clientUA=' + AuthData.ClientUA);
30583102
AuthData.Token && (signUrl += '&token=' + AuthData.Token);
3103+
queryParamsStr && (signUrl += '&' + queryParamsStr);
30593104
setTimeout(function () {
30603105
callback(null, {Url: signUrl});
30613106
});
30623107
});
3108+
30633109
if (AuthData) {
3064-
return url + '?' + AuthData.Authorization +
3110+
syncUrl += '?' + AuthData.Authorization +
30653111
(AuthData.SecurityToken ? '&x-cos-security-token=' + AuthData.SecurityToken : '');
3066-
} else {
3067-
return url;
3112+
queryParamsStr && (syncUrl += '&' + queryParamsStr);
30683113
}
3114+
return syncUrl;
30693115
}
30703116

30713117

@@ -3498,6 +3544,13 @@ function _submitRequest(params, callback) {
34983544
if (params.action) {
34993545
url = url + '?' + params.action;
35003546
}
3547+
if (params.qsStr) {
3548+
if(url.indexOf('?') > -1){
3549+
url = url + '&' + params.qsStr;
3550+
}else{
3551+
url = url + '?' + params.qsStr;
3552+
}
3553+
}
35013554

35023555
var opt = {
35033556
method: method,
@@ -3828,6 +3881,7 @@ var API_MAP = {
38283881
multipartAbort: multipartAbort,
38293882

38303883
// 工具方法
3884+
request: request,
38313885
getObjectUrl: getObjectUrl,
38323886
getAuth: getAuth,
38333887
getV4Auth: getV4Auth,

sdk/util.js

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,34 @@ function camSafeUrlEncode(str) {
1515
.replace(/\*/g, '%2A');
1616
}
1717

18+
var getObjectKeys = function (obj, forKey) {
19+
var list = [];
20+
for (var key in obj) {
21+
if (obj.hasOwnProperty(key)) {
22+
list.push(forKey ? camSafeUrlEncode(key).toLowerCase() : key);
23+
}
24+
}
25+
return list.sort(function (a, b) {
26+
a = a.toLowerCase();
27+
b = b.toLowerCase();
28+
return a === b ? 0 : (a > b ? 1 : -1);
29+
});
30+
};
31+
32+
var obj2str = function (obj) {
33+
var i, key, val;
34+
var list = [];
35+
var keyList = getObjectKeys(obj);
36+
for (i = 0; i < keyList.length; i++) {
37+
key = keyList[i];
38+
val = (obj[key] === undefined || obj[key] === null) ? '' : ('' + obj[key]);
39+
key = camSafeUrlEncode(key).toLowerCase();
40+
val = camSafeUrlEncode(val) || '';
41+
list.push(key + '=' + val)
42+
}
43+
return list.join('&');
44+
};
45+
1846
//测试用的key后面可以去掉
1947
var getAuth = function (opt) {
2048
opt = opt || {};
@@ -38,34 +66,6 @@ var getAuth = function (opt) {
3866
if (!SecretId) throw new Error('missing param SecretId');
3967
if (!SecretKey) throw new Error('missing param SecretKey');
4068

41-
var getObjectKeys = function (obj, forKey) {
42-
var list = [];
43-
for (var key in obj) {
44-
if (obj.hasOwnProperty(key)) {
45-
list.push(forKey ? camSafeUrlEncode(key).toLowerCase() : key);
46-
}
47-
}
48-
return list.sort(function (a, b) {
49-
a = a.toLowerCase();
50-
b = b.toLowerCase();
51-
return a === b ? 0 : (a > b ? 1 : -1);
52-
});
53-
};
54-
55-
var obj2str = function (obj) {
56-
var i, key, val;
57-
var list = [];
58-
var keyList = getObjectKeys(obj);
59-
for (i = 0; i < keyList.length; i++) {
60-
key = keyList[i];
61-
val = (obj[key] === undefined || obj[key] === null) ? '' : ('' + obj[key]);
62-
key = camSafeUrlEncode(key).toLowerCase();
63-
val = camSafeUrlEncode(val) || '';
64-
list.push(key + '=' + val)
65-
}
66-
return list.join('&');
67-
};
68-
6969
// 签名有效起止时间
7070
var now = Math.round(getSkewTime(opt.SystemClockOffset) / 1000) - 1;
7171
var exp = now;
@@ -652,6 +652,7 @@ var util = {
652652
callbackAfterStreamFinish: callbackAfterStreamFinish,
653653
getV4Auth: getV4Auth,
654654
isBrowser: false,
655+
obj2str: obj2str,
655656
};
656657

657658
module.exports = util;

0 commit comments

Comments
 (0)