有的時候需要上傳比較大的文件,但是相同的文件可能已經(jīng)上傳過了绊起。再傳一遍精拟?流量傷不起。怎么解決虱歪?
可以先獲取文件的MD5摘要傳給服務(wù)端蜂绎,如果發(fā)現(xiàn)之前已經(jīng)上傳過,那么就不需要再上傳真正的文件了笋鄙。
//獲取文件的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 但實際測試發(fā)現(xiàn)使用 1000 * 1000 得到的結(jié)果更精確践美,至于到底用哪個洗贰,我也拿不準(zhǔn),請自便)
2陨倡、計算文件大小屬于耗時操作,如果文件比較大,那么在主線程用此方法會卡住主線程,造成用戶體驗很差;所以,調(diào)用此方法應(yīng)該放在子線程
*/