NSURLConnection下载大小文件,断点下载

服务器关闭,只能截图加上代码说明,断点续传是需要服务器支持的

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%@",NSHomeDirectory());
    _data = [[NSMutableData alloc]init ];
}

- (NSString *)filePath
{
    return [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/largeFile.zip"];
}

//下载比较小的文件
- (IBAction)downLoadSmallFile:(UIButton *)sender
{
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/FileUploadServer/LoginServer.zip"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
    [connection start];
}

//下载大文件
- (IBAction)downLoadLargeFile:(UIButton *)sender
{
    //如果目前已经正在下载,那么不再发起下载请求
    if (_connection)
    {
        return;
    }
    //由于内存有限,下载大文件时不能将下载的数据全部存入内存,需要把每次得到的数据直接存入文件(硬盘)
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/FileUploadServer/net.zip"];
    
    //如果需要断点续传,那么在发送下载请求时,需要告诉服务器本地已经下载了多少数据,服务器就会把该资源这部分数据之后的数据发给客户端
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    //把已经下载好的数据大小放入请求头
    //attributesOfItemAtPath  获取一个文件的属性,属性中包括这个文件的大小
    NSDictionary *attDic = [[NSFileManager defaultManager]attributesOfItemAtPath:[self filePath] error:nil];
    //获得当前已经下载的文件大小
    long long downloadSize = [attDic fileSize];
    //addValue: forHTTPHeaderField 给请求头添加一个字段。  bytes=%lld- (固定格式)
    //请求头中Range字段表示本次请求的请求范围
    [request addValue:[NSString stringWithFormat:@"bytes=%lld-",downloadSize] forHTTPHeaderField:@"Range"];
    _connection = [NSURLConnection connectionWithRequest:request delegate:self];
    [_connection start];
}

//暂停下载
- (IBAction)stopDownload:(UIButton *)sender
{
    //取消连接请求,就会终止下载
    [_connection cancel];
    _connection = nil;
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"%@",error);
    _connection = nil;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    //[_data setData:[NSData data]];
    
    //获取响应头的内容,里面包含文件总大小
    NSLog(@"响应%@",response);
    //"Content-Length" = 450825214;  下载的内容大小
    
    NSDictionary *attDic = [[NSFileManager defaultManager]attributesOfItemAtPath:[self filePath] error:nil];
    //断点下载时,收到响应时需要读取已经下载的文件的大小
    _downloadSize = [attDic fileSize];
    NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
    //allHeaderFields  获得响应头,里面是一个字典
    //Content-Length  本次请求的请求体中数据的长度
    //从响应头中获得本次下载的文件总大小
    //如果是断点下载,那么文件的总大小=本次下载的数据长度 + 已经下载的数据长度
    _fileSize = [[resp.allHeaderFields objectForKey:@"Content-Length"]longLongValue] + _downloadSize;
    
    //对于断点下载,需要先判断下载文件是否存在,如果不存在就创建一个空文件用于存储下载数据,如果已经存在,那么直接打开。
    if (![[NSFileManager defaultManager]fileExistsAtPath:[self filePath]])
    {
        //对于大文件,准备一个空文件,用于存储下载的数据
        [[NSFileManager defaultManager]createFileAtPath:[self filePath] contents:nil attributes:nil];
    }
    //NSFileHandle  文件编辑器, 能够读取或修改一个文件的内容
    //fileHandleForWritingAtPath  创建文件编辑器用于写入
    _handle = [[NSFileHandle fileHandleForWritingAtPath:[self filePath]]retain];
    //seekToEndOfFile  把文件的编辑位置移动到文件末尾(光标开始在最前面,如果接着下载会把数据放在前面开始替换已经下载好的数据)
    [_handle seekToEndOfFile];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //[_data appendData:data];
    //把这次返回的数据加入到已经下载的大小中
    _downloadSize = _downloadSize + data.length;
    //计算下载速度
    _progressView.progress = (double)_downloadSize /(double) _fileSize;
    //显示下载进度百分比  百分号占位符 %%
    _percentLabel.text = [NSString stringWithFormat:@"%.2f%%",_progressView.progress*100];
    //把得到的数据写入文件
    [_handle writeData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //[_data writeToFile:[NSHomeDirectory()stringByAppendingPathComponent:@"Documents/MyFile.zip"] atomically:YES];
    //关闭文件编辑器
    [_handle closeFile];
    [_handle release];
    _handle = nil;
    NSLog(@"下载完毕!");
    _connection = nil;
}
 

你可能感兴趣的:(断点下载,NSURLConnection)