Skip to content

Commit

Permalink
上传支持 AddMetaMd5
Browse files Browse the repository at this point in the history
  • Loading branch information
carsonxu committed Aug 1, 2019
1 parent 746e580 commit 3c291b4
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 131 deletions.
12 changes: 8 additions & 4 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ var getAuthorization = function (options, callback) {
// 格式一、(推荐)后端通过获取临时密钥给到前端,前端计算签名
// 服务端 JS 和 PHP 例子:https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/
// 服务端其他语言参考 COS STS SDK :https://github.com/tencentyun/qcloud-cos-sts-sdk
// var url = 'http://127.0.0.1:3000/sts';
var url = '../server/sts.php';
// var url = '../server/sts.php'; // 如果起的是 php server 用这个
var url = '/sts'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function (e) {
Expand All @@ -54,7 +54,8 @@ var getAuthorization = function (options, callback) {

// // 格式二、(推荐)【细粒度控制权限】后端通过获取临时密钥给到前端,前端只有相同请求才重复使用临时密钥,后端可以通过 Scope 细粒度控制权限
// // 服务端例子:https://github.com/tencentyun/qcloud-cos-sts-sdk/edit/master/scope.md
// var url = 'http://127.0.0.1:3000/sts-scope';
// // var url = '../server/sts.php'; // 如果起的是 php server 用这个
// var url = '/sts-scope'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
// var xhr = new XMLHttpRequest();
// xhr.open('POST', url, true);
// xhr.setRequestHeader('Content-Type', 'application/json');
Expand Down Expand Up @@ -124,7 +125,7 @@ var getAuthorization = function (options, callback) {
};

var cos = new COS({
getAuthorization: getAuthorization
getAuthorization: getAuthorization,
});

var TaskId;
Expand Down Expand Up @@ -776,6 +777,9 @@ function selectFileToUpload() {
onTaskReady: function (tid) {
TaskId = tid;
},
onHashProgress: function (progressData) {
logger.log('onHashProgress', JSON.stringify(progressData));
},
onProgress: function (progressData) {
logger.log(JSON.stringify(progressData));
},
Expand Down
3 changes: 2 additions & 1 deletion demo/queue/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var cos = new COS({
ChunkParallelLimit: 5,
ChunkMbSize: 8 * 1024 * 1024,
getAuthorization: function (options, callback) {
var url = '../../server/sts.php';
var url = '/sts';
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function (e) {
Expand Down Expand Up @@ -39,6 +39,7 @@ new Vue({
created: function () {
var self = this;
cos.on('list-update', function (data) {
console.log('list-update');
self.list = data.list;
self.total = data.list.length;
});
Expand Down
157 changes: 113 additions & 44 deletions dist/cos-js-sdk-v5.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,30 @@ var readAsBinaryString = function (blob, callback) {
};

// 获取文件 md5 值
var getFileMd5 = function (blob, callback) {
readAsBinaryString(blob, function (content) {
var hash = md5(content, true);
callback(null, hash);
});
var md5ChunkSize = 1024 * 1024 * 100;
var getFileMd5 = function (blob, callback, onProgress) {
var size = blob.size;
var loaded = 0;
var md5ctx = md5.getCtx();
var next = function (start) {
if (start >= size) {
var hash = md5ctx.digest('hex');
callback(null, hash);
return;
}
var end = Math.min(size, start + md5ChunkSize);
util.fileSlice(blob, start, end, false, function (chunk) {
readAsBinaryString(chunk, function (content) {
chunk = null;
md5ctx = md5ctx.update(content, true);
loaded += content.length;
content = null;
if (onProgress) onProgress({ loaded: loaded, total: size, percent: Math.round(loaded / size * 10000) / 10000 });
next(start + md5ChunkSize);
});
});
};
next(0);
};

function clone(obj) {
Expand Down Expand Up @@ -603,15 +622,15 @@ util.getFileUUID = function (file, ChunkSize) {
return null;
}
};
util.getBodyMd5 = function (UploadCheckContentMd5, Body, callback) {
util.getBodyMd5 = function (UploadCheckContentMd5, Body, callback, onProgress) {
callback = callback || noop;
if (UploadCheckContentMd5) {
if (typeof Body === 'string') {
callback(util.md5(Body, true));
} else if (Blob && Body instanceof Blob) {
util.getFileMd5(Body, function (err, md5) {
callback(md5);
});
}, onProgress);
} else {
callback();
}
Expand Down Expand Up @@ -1957,6 +1976,7 @@ var defaultOptions = {
CorrectClockSkew: true,
SystemClockOffset: 0, // 单位毫秒,ms
UploadCheckContentMd5: false,
UploadAddMetaMd5: false,
UploadIdCacheLimit: 50
};

Expand Down Expand Up @@ -2112,6 +2132,53 @@ function md51(s) {
return state;
}

var binaryBase64 = function (str) {
var i,
len,
char,
res = '';
for (i = 0, len = str.length / 2; i < len; i++) {
char = parseInt(str[i * 2] + str[i * 2 + 1], 16);
res += String.fromCharCode(char);
}
return btoa(res);
};
function getCtx() {
var ctx = {};
ctx.state = [1732584193, -271733879, -1732584194, 271733878];
ctx.tail = '';
ctx.size = 0;
ctx.update = function (s, isBinaryString) {
if (!isBinaryString) s = Utf8Encode(s);
ctx.size += s.length;
s = ctx.tail + s;
var i,
state = ctx.state;
for (i = 64; i <= s.length; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)));
}
ctx.tail = s.substring(i - 64);
return ctx;
};
ctx.digest = function (encode) {
var i,
n = ctx.size,
state = ctx.state,
s = ctx.tail,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < s.length; i++) tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
tail[i >> 2] |= 0x80 << (i % 4 << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i++) tail[i] = 0;
}
tail[14] = n * 8;
md5cycle(state, tail);
return encode === 'hex' ? hex(state) : encode === 'base64' ? binaryBase64(hex(state)) : state;
};
return ctx;
}

/* there needs to be support for Unicode here,
* unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps
Expand Down Expand Up @@ -2194,6 +2261,8 @@ if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
};
}

md5.getCtx = getCtx;

module.exports = md5;

/***/ }),
Expand Down Expand Up @@ -4927,8 +4996,13 @@ function putObject(params, callback) {
var ContentType = headers['Content-Type'] || params.Body && params.Body.type;
!headers['Content-Type'] && ContentType && (headers['Content-Type'] = ContentType);

util.getBodyMd5(self.options.UploadCheckContentMd5, params.Body, function (md5) {
md5 && (params.Headers['Content-MD5'] = util.binaryBase64(md5));
var needCalcMd5 = params.AddMetaMd5 || self.options.UploadAddMetaMd5 || self.options.UploadCheckContentMd5;
util.getBodyMd5(needCalcMd5, params.Body, function (md5) {
if (md5) {
if (self.options.UploadCheckContentMd5) params.Headers['Content-MD5'] = util.binaryBase64(md5);
if (params.AddMetaMd5 || self.options.UploadAddMetaMd5) params.Headers['x-cos-meta-md5'] = md5;
}

if (params.ContentLength !== undefined) {
params.Headers['Content-Length'] = params.ContentLength;
}
Expand Down Expand Up @@ -4967,7 +5041,7 @@ function putObject(params, callback) {
}
callback(null, data);
});
});
}, params.onHashProgress);
}

/**
Expand Down Expand Up @@ -5380,43 +5454,35 @@ function restoreObject(params, callback) {
*/
function multipartInit(params, callback) {

var xml;
var self = this;
var headers = params.Headers;
var userAgent = navigator && navigator.userAgent || '';
if (location.protocol === 'http:' && /TBS\/(\d{6})/.test(userAgent) && /Android\/(\d{6})/.test(userAgent) && /MQQBrowser\/[\d.]+/.test(userAgent) && /MicroMessenger\/[\d.]+/.test(userAgent)) {
xml = util.json2xml({});
headers['Content-MD5'] = util.binaryBase64(util.md5(xml));
// 如果没有 Content-Type 指定一个
if (!headers['Content-Type']) {
headers['Content-Type'] = params.Body && params.Body.type || 'application/octet-stream';
}
}

// 特殊处理 Cache-Control
!headers['Cache-Control'] && (headers['Cache-Control'] = '');

submitRequest.call(this, {
Action: 'name/cos:InitiateMultipartUpload',
method: 'POST',
Bucket: params.Bucket,
Region: params.Region,
Key: params.Key,
action: 'uploads',
headers: params.Headers,
body: xml
}, function (err, data) {
if (err) {
return callback(err);
}
data = util.clone(data || {});
if (data && data.InitiateMultipartUploadResult) {
return callback(null, util.extend(data.InitiateMultipartUploadResult, {
statusCode: data.statusCode,
headers: data.headers
}));
}
callback(null, data);
});
util.getBodyMd5(params.AddMetaMd5 || self.options.UploadAddMetaMd5, params.Body, function (md5) {
if (md5) params.Headers['x-cos-meta-md5'] = md5;
submitRequest.call(self, {
Action: 'name/cos:InitiateMultipartUpload',
method: 'POST',
Bucket: params.Bucket,
Region: params.Region,
Key: params.Key,
action: 'uploads',
headers: params.Headers
}, function (err, data) {
if (err) {
return callback(err);
}
data = util.clone(data || {});
if (data && data.InitiateMultipartUploadResult) {
return callback(null, util.extend(data.InitiateMultipartUploadResult, {
statusCode: data.statusCode,
headers: data.headers
}));
}
callback(null, data);
});
}, params.onHashProgress);
}

/**
Expand All @@ -5440,7 +5506,7 @@ function multipartUpload(params, callback) {
var self = this;
util.getFileSize('multipartUpload', params, function () {
util.getBodyMd5(self.options.UploadCheckContentMd5, params.Body, function (md5) {
md5 && (params.Headers['Content-MD5'] = util.binaryBase64(md5));
if (md5) params.Headers['Content-MD5'] = util.binaryBase64(md5);
submitRequest.call(self, {
Action: 'name/cos:UploadPart',
TaskId: params.TaskId,
Expand Down Expand Up @@ -6088,6 +6154,9 @@ function submitRequest(params, callback) {
params.action && (Query[params.action] = '');

var next = function (tryIndex) {
if (!self.options) {
debugger;
}
var oldClockOffset = self.options.SystemClockOffset;
getAuthorizationAsync.call(self, {
Bucket: params.Bucket || '',
Expand Down
49 changes: 48 additions & 1 deletion lib/md5.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,51 @@ function md51(s) {
return state;
}


var binaryBase64 = function (str) {
var i, len, char, res = '';
for (i = 0, len = str.length / 2; i < len; i++) {
char = parseInt(str[i * 2] + str[i * 2 + 1], 16);
res += String.fromCharCode(char);
}
return btoa(res);
};
function getCtx() {
var ctx = {};
ctx.state = [1732584193, -271733879, -1732584194, 271733878];
ctx.tail = '';
ctx.size = 0;
ctx.update = function (s, isBinaryString) {
if (!isBinaryString) s = Utf8Encode(s);
ctx.size += s.length;
s = ctx.tail + s;
var i, state = ctx.state;
for (i=64; i<=s.length; i+=64) {
md5cycle(state, md5blk(s.substring(i-64, i)));
}
ctx.tail = s.substring(i-64);
return ctx;
};
ctx.digest = function (encode) {
var i,
n = ctx.size,
state = ctx.state,
s = ctx.tail,
tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
for (i=0; i<s.length; i++)
tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);
tail[i>>2] |= 0x80 << ((i%4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i=0; i<16; i++) tail[i] = 0;
}
tail[14] = n*8;
md5cycle(state, tail);
return encode === 'hex' ? hex(state) : encode === 'base64' ? binaryBase64(hex(state)) : state;
};
return ctx;
}

/* there needs to be support for Unicode here,
* unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps
Expand Down Expand Up @@ -203,4 +248,6 @@ if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
}
}

module.exports = md5;
md5.getCtx = getCtx;

module.exports = md5;
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
},
"homepage": "https://github.com/tencentyun/cos-js-sdk-v5#readme",
"dependencies": {
"xmldom": "^0.1.27"
"body-parser": "^1.18.3",
"qcloud-cos-sts": "^3.0.0",
"express": "^4.16.4"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"body-parser": "^1.18.3",
"express": "^4.16.4",
"qcloud-cos-sts": "^2.0.7",
"request": "^2.87.0",
"webpack": "^3.8.1"
"webpack": "^3.8.1",
"xmldom": "^0.1.27"
}
}
Loading

0 comments on commit 3c291b4

Please sign in to comment.