获取文件的MD5摘要、计算文件大小

有的时候需要上传比较大的文件,但是相同的文件可能已经上传过了。再传一遍?流量伤不起。怎么解决?

可以先获取文件的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、计算文件大小属于耗时操作,如果文件比较大,那么在主线程用此方法会卡住主线程,造成用户体验很差;所以,调用此方法应该放在子线程
*/

你可能感兴趣的:(获取文件的MD5摘要、计算文件大小)