七牛是否有获取文件HASH的API?

如题,七年是否有获取文件HASH的API?这样可以更方便做一些文件完整性校验。

我的场景是一个音乐播放器,由于HTML5没有媒体缓存的功能,因此在本机搭了一个HTTP代理来处理缓存。但是如果用户有手工拉取媒体进度,则有可能导致请求回来的数据连接起来不是完整的文件,请问七牛是否有类似MD5、SHA1之类的信息可以供文件完整性校验?

补充,我自己又仔细看了一下,七牛有提供etag作为HASH,地址在这里http://developer.qiniu.com/docs/v6/api/overview/appendix.html

但是试了一下,大于4M的算出来和线上完全不一致,求解。

function getEtag(buffer){
    // 以4M为单位分割
    var sliceSize = 4*1024*1024;
    var bufferSize = buffer.length;
    var blockCount = Math.ceil(bufferSize / sliceSize);
    console.log(blockCount);
    var prefix;
    if(blockCount > 1){
        prefix = 0x96;
    }else{
        prefix = 0x16
    }

    var sha1String = [new Buffer([prefix])];
    var sha1Length = 1;

    for(var i=0;i<blockCount;i++){
        sha1String.push(sha1(buffer.slice(i*sliceSize,(i+1)*sliceSize)));
        sha1Length += 20;
    }

    var sha1Buffer = Buffer.concat(sha1String,sha1Length);

    if(blockCount > 1){
        sha1Buffer = sha1(sha1Buffer);
    }

    return sha1Buffer.toString('base64');
}

    function sha1(content){
        var crypto = require('crypto');
        var sha1 = crypto.createHash('sha1');
        sha1.update(content);
        return sha1.digest();
    }

阅读 10.7k
5 个回答

自问自答,七牛有提供文件的hash算法,在HTTP响应头以及各种API和工具中用stat都可以看到这个hash值。算法见http://developer.qiniu.com/docs/v6/api/overview/appendix.html

利用这个hash就可以校验文件的完整性。

上面代码中犯了顺序错误,也是因为文档描述有误,花了好久,参考PHP的代码(https://github.com/qiniu/qetag),一步一步调试对比,最后发现七牛文档中描述的方式不对。

文档中说大于4M的文件,分割以后分别计算sha1,然后:

3.将所有sha1值按切块顺序拼接,并在最前面拼上单个字节,值为0x96;
4.对拼接好的二进制数据做再做sha1计算;
5.对前一步的sha1值做url_safe_base64计算,所得结果即为ETag值。

注意这里的描述说的是先拼接(含0x96),再sha1,最后再base64。但实际算法是:先把文件块的sha1拼接起来(不含0x96),对拼接后的数据做sha1,最后拼接上0x96,再做base64,也就是说0x96的拼接时机描述是错误的。(我之前也一直在怀疑,4M以内的base64之前为21位,为何4M以上的base64之前为20位?)

附上完整代码:

function getEtag(buffer){
    // 以4M为单位分割
    var sliceSize = 4*1024*1024;
    var bufferSize = buffer.length;
    var blockCount = Math.ceil(bufferSize / sliceSize);
    var prefix;
    if(blockCount > 1){
        prefix = 0x96;
    }else{
        prefix = 0x16
    }

    var sha1String = [];
    var sha1Length = 0;

    for(var i=0;i<blockCount;i++){
        sha1String.push(sha1(buffer.slice(i*sliceSize,(i+1)*sliceSize)));
        sha1Length += 20;
    }

    var sha1Buffer = Buffer.concat(sha1String,sha1Length);

    if(blockCount > 1){
        sha1Buffer = sha1(sha1Buffer);
    }

    sha1Buffer = Buffer.concat([new Buffer([prefix]),sha1Buffer],sha1Buffer.length + 1);

    return sha1Buffer.toString('base64')
        .replace(/\//g,'_').replace(/\+/g,'_');

    function sha1(content){
        var crypto = require('crypto');
        var sha1 = crypto.createHash('sha1');
        sha1.update(content);
        return sha1.digest();
    }
}
新手上路,请多包涵

貌似木有,自己hash当文件名吧.

新手上路,请多包涵

from qiniu import utils
file_hash = utils.etag(filePath)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进