Skip to content

Commit 9eca5ee

Browse files
committed
2 parents c516a9b + 4aaf55b commit 9eca5ee

File tree

4 files changed

+146
-13
lines changed

4 files changed

+146
-13
lines changed

demo/demo-post-policy.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
var config = require('./config');
2+
3+
var uploadFile = function () {
4+
// 请求用到的参数
5+
// var prefix = 'https://cos.' + config.Region + '.myqcloud.com/' + config.Bucket + '/'; // 这个是后缀式,签名也要指定 Pathname: '/' + config.Bucket + '/'
6+
var prefix = 'https://' + config.Bucket + '.cos.' + config.Region + '.myqcloud.com/';
7+
8+
// 对更多字符编码的 url encode 格式
9+
var camSafeUrlEncode = function (str) {
10+
return encodeURIComponent(str)
11+
.replace(/!/g, '%21')
12+
.replace(/'/g, '%27')
13+
.replace(/\(/g, '%28')
14+
.replace(/\)/g, '%29')
15+
.replace(/\*/g, '%2A');
16+
};
17+
18+
// 获取临时密钥
19+
var getCredentials = function (options, callback) {
20+
wx.request({
21+
method: 'GET',
22+
url: 'http://127.0.0.1:3000/post-policy?key=' + encodeURIComponent(options.Key), // 服务端签名,参考 server 目录下的两个签名例子
23+
dataType: 'json',
24+
success: function (result) {
25+
var data = result.data;
26+
if (data) {
27+
callback(data);
28+
} else {
29+
wx.showModal({title: '临时密钥获取失败', content: JSON.stringify(data), showCancel: false});
30+
}
31+
},
32+
error: function (err) {
33+
wx.showModal({title: '临时密钥获取失败', content: JSON.stringify(err), showCancel: false});
34+
}
35+
});
36+
};
37+
38+
// 上传文件
39+
var uploadFile = function (filePath) {
40+
var Key = filePath.substr(filePath.lastIndexOf('/') + 1); // 这里指定上传的文件名
41+
getCredentials({Key: Key}, function (credentials) {
42+
var formData = {
43+
'key': Key,
44+
'success_action_status': 200,
45+
'Content-Type': '',
46+
'q-sign-algorithm': credentials.qSignAlgorithm,
47+
'q-ak': credentials.qAk,
48+
'q-key-time': credentials.qKeyTime,
49+
'q-signature': credentials.qSignature,
50+
'policy': credentials.policy,
51+
};
52+
if (credentials.securityToken) formData['x-cos-security-token'] = credentials.securityToken;
53+
var requestTask = wx.uploadFile({
54+
url: prefix,
55+
name: 'file',
56+
filePath: filePath,
57+
formData: formData,
58+
success: function (res) {
59+
var url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
60+
if (res.statusCode === 200) {
61+
wx.showModal({title: '上传成功', content: url, showCancel: false});
62+
} else {
63+
wx.showModal({title: '上传失败', content: JSON.stringify(res), showCancel: false});
64+
}
65+
console.log(res.statusCode);
66+
console.log(url);
67+
},
68+
fail: function (res) {
69+
wx.showModal({title: '上传失败', content: JSON.stringify(res), showCancel: false});
70+
}
71+
});
72+
requestTask.onProgressUpdate(function (res) {
73+
console.log('正在进度:', res);
74+
});
75+
});
76+
};
77+
78+
// 选择文件
79+
wx.chooseImage({
80+
count: 1, // 默认9
81+
sizeType: ['original'], // 可以指定是原图还是压缩图,这里默认用原图
82+
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
83+
success: function (res) {
84+
uploadFile(res.tempFiles[0].path);
85+
}
86+
})
87+
};
88+
89+
module.exports = uploadFile;

demo/pages/index/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//index.js
22
var demoSdk = require('../../demo-sdk');
3-
var demoNoSdk = require('../../demo-no-sdk');
3+
var simpleUpload = require('../../demo-no-sdk');
4+
var postUpload = require('../../demo-post-policy');
45

56
var option = {
67
data: {
@@ -15,7 +16,8 @@ for (var key in demoSdk) {
1516
}
1617
}
1718

18-
option.simpleUpload = demoNoSdk;
19+
option.postUpload = postUpload;
20+
option.simpleUpload = simpleUpload;
1921

2022
//获取应用实例
2123
Page(option);

demo/pages/index/index.wxml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
<view class="container">
33
<view class="title">不使用 SDK 简单上传例子(推荐)</view>
44
<view class="list">
5-
<button type="primary" class="button" bindtap="simpleUpload"><text style="font-weight:bold;">[推荐]</text> 不使用 SDK 简单上传</button>
5+
<button type="primary" class="button" bindtap="postUpload"><text style="font-weight:bold;">[推荐]</text> 不使用 SDK 简单上传1</button>
6+
<button type="primary" class="button" bindtap="simpleUpload"><text style="font-weight:bold;">[推荐]</text> 不使用 SDK 简单上传2</button>
67
</view>
78
<view class="title">小程序完整 SDK 例子(功能齐全,文件较大)</view>
89
<view class="list">

server/sts.js

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// 临时密钥服务例子
2-
var STS = require('qcloud-cos-sts');
32
var bodyParser = require('body-parser');
3+
var STS = require('qcloud-cos-sts');
44
var express = require('express');
5+
var crypto = require('crypto');
56

67
// 配置参数
78
var config = {
@@ -52,9 +53,8 @@ app.all('/sts', function (req, res, next) {
5253
'statement': [{
5354
'action': config.allowActions,
5455
'effect': 'allow',
55-
'principal': {'qcs': ['*']},
5656
'resource': [
57-
'qcs::cos:ap-guangzhou:uid/' + AppId + ':prefix//' + AppId + '/' + ShortBucketName + '/' + config.allowPrefix,
57+
'qcs::cos:' + config.region + ':uid/' + AppId + ':prefix//' + AppId + '/' + ShortBucketName + '/' + config.allowPrefix,
5858
],
5959
}],
6060
};
@@ -63,12 +63,12 @@ app.all('/sts', function (req, res, next) {
6363
secretId: config.secretId,
6464
secretKey: config.secretKey,
6565
proxy: config.proxy,
66+
region: config.region,
6667
durationSeconds: config.durationSeconds,
6768
policy: policy,
6869
}, function (err, tempKeys) {
69-
var result = JSON.stringify(err || tempKeys) || '';
70-
result.startTime = startTime;
71-
res.send(result);
70+
if (tempKeys) tempKeys.startTime = startTime;
71+
res.send(err || tempKeys);
7272
});
7373
});
7474

@@ -105,15 +105,56 @@ app.all('/sts', function (req, res, next) {
105105
// durationSeconds: config.durationSeconds,
106106
// policy: policy,
107107
// }, function (err, tempKeys) {
108-
// var result = JSON.stringify(err || tempKeys) || '';
109-
// result.startTime = startTime;
110-
// res.send(result);
108+
// if (tempKeys) tempKeys.startTime = startTime;
109+
// res.send(err || tempKeys);
111110
// });
112111
// });
112+
//
113+
// 用于 PostObject 签名保护
114+
app.all('/post-policy', function (req, res, next) {
115+
var query = req.query;
116+
var now = Math.round(Date.now() / 1000);
117+
var exp = now + 900;
118+
var qKeyTime = now + ';' + exp;
119+
var qSignAlgorithm = 'sha1';
120+
var policy = JSON.stringify({
121+
'expiration': new Date(exp * 1000).toISOString(),
122+
'conditions': [
123+
// {'acl': query.ACL},
124+
// ['starts-with', '$Content-Type', 'image/'],
125+
// ['starts-with', '$success_action_redirect', redirectUrl],
126+
// ['eq', '$x-cos-server-side-encryption', 'AES256'],
127+
{'q-sign-algorithm': qSignAlgorithm},
128+
{'q-ak': config.secretId},
129+
{'q-sign-time': qKeyTime},
130+
{'bucket': config.bucket},
131+
{'key': query.key},
132+
]
133+
});
134+
135+
// 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
136+
// 步骤一:生成 SignKey
137+
var signKey = crypto.createHmac('sha1', config.secretKey).update(qKeyTime).digest('hex');
113138

139+
// 步骤二:生成 StringToSign
140+
var stringToSign = crypto.createHash('sha1').update(policy).digest('hex');
141+
142+
// 步骤三:生成 Signature
143+
var qSignature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');
144+
145+
console.log(policy);
146+
res.send({
147+
policyObj: JSON.parse(policy),
148+
policy: Buffer.from(policy).toString('base64'),
149+
qSignAlgorithm: qSignAlgorithm,
150+
qAk: config.secretId,
151+
qKeyTime: qKeyTime,
152+
qSignature: qSignature,
153+
// securityToken: securityToken, // 如果使用临时密钥,要返回在这个资源 sessionToken 的值
154+
});
155+
});
114156

115157
app.all('*', function (req, res, next) {
116-
res.writeHead(404);
117158
res.send({code: -1, message: '404 Not Found'});
118159
});
119160

0 commit comments

Comments
 (0)