获取文件的MD5摘要、计算文件大小
2018-11-02 本文已影响15人
MxlZlh
有的时候需要上传比较大的文件,但是相同的文件可能已经上传过了。再传一遍?流量伤不起。怎么解决?
可以先获取文件的MD5摘要传给服务端,如果发现之前已经上传过,那么就不需要再上传真正的文件了。
//获取文件的MD5摘要
- (NSString *)md5WithFilePath:(NSString *)path {
NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:path];
if( handle == nil ) {
return nil;
}
CC_MD5_CTX md5;
CC_MD5_Init(&md5);
BOOL done = NO;
while(!done)
{
NSData* fileData = [handle readDataOfLength: 256 ];
CC_MD5_Update(&md5, [fileData bytes], (CC_LONG)[fileData length]);
if( [fileData length] == 0 )
done = YES;
}
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(digest, &md5);
NSString* s = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1],
digest[2], digest[3],
digest[4], digest[5],
digest[6], digest[7],
digest[8], digest[9],
digest[10], digest[11],
digest[12], digest[13],
digest[14], digest[15]];
return s;
}
顺便,我们再计算下文件/文件夹的大小
+ (long long)fileSizeAtPath:(NSString*)filePath
{
NSFileManager* manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePath]){
return [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
}
return 0;
}
+ (float)folderSizeAtPath:(NSString *)folderPath
{
NSFileManager* manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:folderPath]) return 0;
NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath:folderPath] objectEnumerator];
NSString* fileName;
long long folderSize = 0;
while ((fileName = [childFilesEnumerator nextObject]) != nil)
{
NSString* fileAbsolutePath = [folderPath stringByAppendingPathComponent:fileName];
folderSize += [self fileSizeAtPath:fileAbsolutePath];
}
return folderSize/(1024.0*1024.0);
}
/**
这里有2个注意点
1、有文章中指出 iOS中1G == 1000Mb ==1000 * 1000Kb == 1000 * 1000 * 1000B(虽然上面的代码中,我写的 1024.0*1024.0 但实际测试发现使用 1000 * 1000 得到的结果更精确,至于到底用哪个,我也拿不准,请自便)
2、计算文件大小属于耗时操作,如果文件比较大,那么在主线程用此方法会卡住主线程,造成用户体验很差;所以,调用此方法应该放在子线程
*/