欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

七牛-ETag算法(OC)

程序员文章站 2022-05-04 14:27:21
一、摘要 1.七牛上传文件,用hash来唯一标识七牛存储空间中的某个文件,该hash是以ETag算法计算出的一段哈希值; 2.算法介绍:https://developer.qiniu.com/kodo/manual/1231/appendix; 3.七牛的提供的实现语言中(https://githu ......

一、摘要

1.七牛上传文件,用hash来唯一标识七牛存储空间中的某个文件,该hash是以etag算法计算出的一段哈希值;

2.算法介绍:;

3.七牛的提供的实现语言中(),没有给出oc实现;

4.参考js代码:;

二、代码

- (void)test2 {
    /*测试链接
     http://yqq.file.mediportal.com.cn/yqq_5b911b43955f06317c6bd792/3974e8eaab11b2dd5b357e60e5a587d1  etag:ftfvrvsdpvf9t_tcfyvsvc-1p6aw
     4m以上文件亲测正确
     */
    
    nsurl *url = [nsurl urlwithstring:@"http://yqq.file.mediportal.com.cn/yqq_5b911b43955f06317c6bd792/3974e8eaab11b2dd5b357e60e5a587d1"];
    nserror *error;
    nsdata * data = [nsdata datawithcontentsofurl:url options:nsdatareadingmapped error:&error];
    nsstring *etag = [self caculateetagwith:data];
    nslog(@"etag------%@", etag);
}

//算法实现
- (nsstring *)caculateetagwith:(nsdata *)data
{
    unsigned long blocksize = 4 * 1024 * 1024;
    nsmutabledata *sha1data = [nsmutabledata data];
    byte prefix = 0x16;
    int blockcount = 0;
    
    unsigned long buffersize = [data length];
    //获取余数
    unsigned long remainder = buffersize % blocksize;
    //获取商
    double fa = (double)buffersize / blocksize;
    //向下取整
    blockcount = floor(fa);
    
    if (buffersize > blocksize) {//大于4m的文件
        nsmutabledata *sha2data = [nsmutabledata data];
        for (int i = 0; i < blockcount+1; i++) {
            nsuinteger length = blocksize;
            if (i == blockcount && remainder > 0) {
                length = remainder;
            }
            //将每个块(包括4m块和小于4m的块)进行sha1加密并拼接起来
            nsdata *subdata = [data subdatawithrange:nsmakerange(i * blocksize, length)];
            [sha2data appenddata:[self sha1:subdata]];
        }
        //将拼接块进行二次sha1加密
        [sha1data appenddata:[self sha1:sha2data]];
    } else {
        [sha1data appenddata:[self sha1:data]];
    }

    if (!sha1data.length) return @"fto5o-5ea0snmlw_75vggjcv2acj";
    
    nsdata *sha1buffer = sha1data;
    if (buffersize > blocksize) {
        //大于4m,头部拼接0x96单个字节
        prefix = 0x96;
    }
    
    byte prebyte[] = {prefix};
    nsmutabledata *mutadata = [nsmutabledata datawithbytes:prebyte length:1];
    [mutadata appenddata:sha1buffer];
    
    //将长度为21个字节的二进制数据进行url_safe_base64计算
    return [self safebase64withsha1str:mutadata];
}

/*
 sha1加密(加密后的data长度为20)
 */
- (nsdata*)sha1:(nsdata *)data
{
    //注:如果用以下代码,转换出的data长度为40
//    const char *cstr = [sourcestr cstringusingencoding:nsutf8stringencoding];
//    nsdata *data = [nsdata datawithbytes:cstr length:sourcestr.length];
//    nsmutablestring* output = [nsmutablestring stringwithcapacity:cc_sha1_digest_length * 2];
//    for(int i = 0; i < cc_sha1_digest_length; i++)
//        [output appendformat:@"%02x", digest[i]];
//    return output;
    
    //sha1data长度为20(cc_sha1_digest_length系统设定为20)
    uint8_t digest[cc_sha1_digest_length];
    cc_sha1(data.bytes, (cc_long)data.length, digest);
    nsdata * sha1data = [[nsdata alloc] initwithbytes:digest length:cc_sha1_digest_length];
    return sha1data;
}

- (nsstring *)safebase64withsha1str:(nsdata *)base64
{
    //base64编码中包含有"+,/,="不安全的url字符串,我们要对这些字符进行转换
    nsstring *base64str = [gtmbase64 encodebase64data:base64];

    nsmutablestring *safebase64str = [[nsmutablestring alloc] initwithstring:base64str];

    safebase64str = (nsmutablestring *)[safebase64str stringbyreplacingoccurrencesofstring:@"+"withstring:@"-"];

    safebase64str = (nsmutablestring *)[safebase64str stringbyreplacingoccurrencesofstring:@"/"withstring:@"_"];

    safebase64str = (nsmutablestring *)[safebase64str stringbyreplacingoccurrencesofstring:@"="withstring:@""];
    
    return safebase64str;
}

说明:url?stat可查看七牛文件的etag值(即hash值),如下:

http://yqq.file.mediportal.com.cn/yqq_5b911b43955f06317c6bd792/3974e8eaab11b2dd5b357e60e5a587d1?stat

     {"fsize":687810,"uploaded":687810,"hash":"ftfvrvsdpvf9t_tcfyvsvc-1p6aw","mimetype":"image/jpeg"}

 

七牛-ETag算法(OC)

 

github