七牛-ETag算法(OC)
程序员文章站
2022-11-21 16:57:56
一、摘要 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"}