diff --git a/.gitignore b/.gitignore index 78f2710..3674c4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ .idea/ +npm-debug.log diff --git a/index.js b/index.js index 8da4625..7924f8b 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,7 @@ var util = require('util') var crypto = require('crypto') var minimatch = require('minimatch') var uploadedFiles = 0; +var getEtag = require('./qetag'); module.exports = function (qiniu, option) { option = option || {}; @@ -32,41 +33,42 @@ module.exports = function (qiniu, option) { if (isIgnore) return next(); var fileKey = option.dir + ((!option.dir || option.dir[option.dir.length - 1]) === '/' ? '' : '/') + (option.versioning ? version + '/' : '') + filePath; - var fileHash = calcHash(file); + getEtag(file.path, function (fileHash) { + qs.push(Q.nbind(qn.stat, qn)(fileKey) + .spread(function (stat) { + // Skip when hash equal + if (stat.hash === fileHash) return false; - qs.push(Q.nbind(qn.stat, qn)(fileKey) - .spread(function (stat) { - // Skip when hash equal - if (stat.hash === fileHash) return false; + // Then delete + return Q.nbind(qn.delete, qn)(fileKey) + }, function () { + // Upload when not exists + return true; + }) + .then(function (isUpload) { + if (isUpload === false) return false; + return Q.nbind(qn.upload, qn)(file._contents, {key: fileKey}) + }) + .then(function (stat) { + // No upload + if (stat === false) { + log('Skip:', colors.grey(filePath)); + return; + } - // Then delete - return Q.nbind(qn.delete, qn)(fileKey) - }, function () { - // Upload when not exists - return true; - }) - .then(function (isUpload) { - if (isUpload === false) return false; - return Q.nbind(qn.upload, qn)(file._contents, {key: fileKey}) - }) - .then(function (stat) { - // No upload - if (stat === false) { - log('Skip:', colors.grey(filePath)); - return; - } - - // Record hash - uploadedFiles++; + // Record hash + uploadedFiles++; - log('Upload:', colors.green(filePath), '→', colors.green(fileKey)); - }, function (err) { - log('Error', colors.red(filePath), new PluginError('gulp-qiniu', err).message); - that.emit('Error', colors.red(filePath), new PluginError('gulp-qiniu', err)); - }) - ) + log('Upload:', colors.green(filePath), '→', colors.green(fileKey)); + }, function (err) { + log('Error', colors.red(filePath), new PluginError('gulp-qiniu', err).message); + that.emit('Error', colors.red(filePath), new PluginError('gulp-qiniu', err)); + }) + ) - next(); + next(); + }); + }, function () { Q.all(qs) .then(function (rets) { @@ -96,21 +98,4 @@ module.exports = function (qiniu, option) { } return target; } - - /** - * Calc qiniu etag - * - * @param file - * @returns {*} - */ - function calcHash(file) { - if (file.size > 1 << 22) return false; - var shasum = crypto.createHash('sha1'); - shasum.update(file._contents); - var sha1 = shasum.digest(); - var hash = new Buffer(1 + sha1.length); - hash[0] = 0x16; - sha1.copy(hash, 1); - return hash.toString('base64').replace('+', '-').replace('/', '_'); - } }; diff --git a/qetag.js b/qetag.js new file mode 100644 index 0000000..f7b04a2 --- /dev/null +++ b/qetag.js @@ -0,0 +1,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 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;