• 七牛-ETag算法(OC)


    一、摘要

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

    2.算法介绍:https://developer.qiniu.com/kodo/manual/1231/appendix

    3.七牛的提供的实现语言中(https://github.com/qiniu/qetag),没有给出OC实现;

    4.参考js代码:https://www.jianshu.com/p/3785fc314fc5

    二、代码

    - (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"}

    GitHub

  • 相关阅读:
    Web安全学习计划
    机器学习资源大全
    推荐引擎的学习资料
    《Servlet与JSP核心编程》读书笔记
    Application "org.eclipse.ui.ide.workbench" could not be found in the registry.问题的解决
    Android 百度地图开发(二)
    Linux系统编程_1_文件夹读取(实现简单ls命令)
    Bootstrap 模态框、轮播 结合使用
    cocos2d-x 3.0游戏实例学习笔记 《跑酷》移植到android手机
    Unique Binary Search Trees II
  • 原文地址:https://www.cnblogs.com/lybSkill/p/11992312.html
Copyright © 2020-2023  润新知