iOS实现文件下载功能

本文实例为大家分享了iOS实现文件下载的具体代码,供大家参考,具体内容如下

说明:

1).获取网络文件大小;

2).开启循环,计算每段position开始与结束位置,通过Range头字段按块获取文件数据流;

3).使用NSFileHandle追加方式将NSData文件数据写入本地文件。

1、用HEAD请求方式获取网络文件大小:

/*
 获取网络文件大小
 */
- (long long)getNetFileLen:(NSURL *)url{
    //1.创建request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10];
    //设置请求方式为HEAD, 只获取头信息
    request.HTTPMethod = @"HEAD";
    
    //2.定义用于接收网络数据的对象
    NSURLResponse *response = nil;
    
    //3.同步请求网络,将结果存入response
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
    
    //返回文件大小
    return response.expectedContentLength;
}

2、开启异步线程,请求网络下载文件:

/*
 下载文件
 */
- (void)downloadFile:(NSString *)urlStr done:(void (^)())done{
    
    //1.获取系统自带全局队列
    //并行队列,多个线程并发执行:DISPATCH_QUEUE_PRIORITY_DEFAULT
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //2.异步执行
    dispatch_async(queue, ^{
        //创建url对象
        NSURL *url = [[NSURL alloc] initWithString:urlStr];
        NSLog(@"url: %@", urlStr);
        
        //获取本地已下载文件大小
        long long localFileLen = [self getLocalFileLen];
        NSLog(@"localFileLen : %lld", localFileLen);
        
        //获取网络文件大小
        long long netFileLen = [self getNetFileLen:url];
        NSLog(@"netFileLen : %lld", netFileLen);
        
        if(localFileLen == netFileLen){//一样表示存在了
            return;
        }
        
        //每次从服务端获取的文件数据大小
        long long itemSize = 1024 * 20;
        
        //一段数据的开始position位置
        long long startPos = 0;
        
        //一段数据的结尾position位置
        long long endPos = 0;
        
        while (startPos < netFileLen) {
            //计算结尾position
            endPos = startPos + itemSize - 1;
            
            //组装range字段,用于请求头
            NSString *range = [NSString stringWithFormat:@"Bytes=%lld-%lld", startPos, endPos];
            
            NSLog(@"range : %@", range);
            
            //重新计算下一段数据开始position
            startPos = startPos + itemSize;
            
            /*
             缓存策略
             NSURLRequestUseProtocolCachePolicy = 0, 默认,内存缓存
             NSURLRequestReloadIgnoringLocalCacheData = 1, 忽略本地内存缓存
             NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
             NSURLRequestReturnCacheDataElseLoad = 2,
             NSURLRequestReturnCacheDataDontLoad = 3,
             */
            
            //(1)创建request
            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
            
            //设置Range请求头
            [request setValue:range forHTTPHeaderField:@"Range"];
            
            //(2)定义用于接收网络信息的对象
            NSURLResponse *response = nil;
            
            //(3)同步请求网络
            NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
            
            //(4)将数据写入文件
            [self appendFile:data];
        }
        
        //3.切回主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            //调用完成方法
            done();
        });
        
    });
}

3、获取本地文件大小:

/*
 获取本地文件大小
 */
- (long long)getLocalFileLen{
    //目录路径
    NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    //文件路径
    NSString *filePath = [cacheDir stringByAppendingPathComponent:@"qq.dmg"];
    //获取本地文件NSDictionary信息
    NSDictionary *map = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL];
    //获取本地文件大小,转为longlong类型
    return [map[NSFileSize] longLongValue];
}

4、将NSData数据追加写入文件:

/*
 将NSData数据追加写入文件
 */
- (void)appendFile:(NSData *)data{
    //目录路径
    NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    //文件路径
    NSString *filePath = [cacheDir stringByAppendingPathComponent:@"qq.dmg"];
    
    NSLog(@"filePath : %@", filePath);
    
    //创建文件操作类,NSFileHandle支持追加写入方式
    NSFileHandle *file = [NSFileHandle fileHandleForWritingAtPath:filePath];
    
    if(!file){//文件不存在时,直接覆盖方式写入
        [data writeToFile:filePath atomically:YES];
        return;
    }
    //跳到文件末尾
    [file seekToEndOfFile];
    
    //写数据
    [file writeData:data];
    
    //关闭文件流
    [file closeFile];
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(iOS实现文件下载功能)