forked from qiniu/qetag
-
Notifications
You must be signed in to change notification settings - Fork 0
/
qetag.js
79 lines (66 loc) · 1.72 KB
/
qetag.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 计算文件的eTag,参数为buffer或者readableStream或者文件路径
function getEtag(buffer,callback){
// 判断传入的参数是buffer还是stream还是filepath
var mode = 'buffer';
if(typeof buffer === 'string'){
buffer = require('fs').createReadStream(buffer);
mode='stream';
}else if(buffer instanceof require('stream')){
mode='stream';
}
// sha1算法
var sha1 = function(content){
var crypto = require('crypto');
var sha1 = crypto.createHash('sha1');
sha1.update(content);
return sha1.digest();
};
// 以4M为单位分割
var blockSize = 4*1024*1024;
var sha1String = [];
var prefix = 0x16;
var blockCount = 0;
switch(mode){
case 'buffer':
var bufferSize = buffer.length;
blockCount = Math.ceil(bufferSize / blockSize);
for(var i=0;i<blockCount;i++){
sha1String.push(sha1(buffer.slice(i*blockSize,(i+1)*blockSize)));
}
process.nextTick(function(){
callback(calcEtag());
});
break;
case 'stream':
var stream = buffer;
stream.on('readable', function() {
var chunk;
while (chunk = stream.read(blockSize)) {
sha1String.push(sha1(chunk));
blockCount++;
}
});
stream.on('end',function(){
callback(calcEtag());
});
break;
}
function calcEtag(){
if(!sha1String.length){
return 'Fto5o-5ea0sNMlW_75VgGJCv2AcJ';
}
var sha1Buffer = Buffer.concat(sha1String,blockCount * 20);
// 如果大于4M,则对各个块的sha1结果再次sha1
if(blockCount > 1){
prefix = 0x96;
sha1Buffer = sha1(sha1Buffer);
}
sha1Buffer = Buffer.concat(
[new Buffer([prefix]),sha1Buffer],
sha1Buffer.length + 1
);
return sha1Buffer.toString('base64')
.replace(/\//g,'_').replace(/\+/g,'-');
}
}
module.exports = getEtag;