大文件下載--斷點續傳--NSURLConnection

有了上一篇文章的鋪墊直接上代碼,下面是分析原理.app

//  ViewController.m
//  大文件下載
//  Created by apple on 15/11/11.
//  Copyright © 2015年 LDSmallCat. All rights reserved.
#import "ViewController.h"
#import "DACircularProgressView.h"//進度條的第三方框架
@interface ViewController ()<NSURLConnectionDataDelegate>
//下載和暫停按鈕
@property (weak, nonatomic) IBOutlet UIButton *button;
//用來寫數據的文件句柄對象
@property(nonatomic,strong) NSFileHandle *writeHandle;
//文件的總大小.用已經下載的進度 除以 文件的總大小,作出進度條
@property(nonatomic,assign) long long totalLength;
//當前已經寫入的文件大小.已經下載的,
@property(nonatomic,assign) long long currentLength;
///連接對象
@property (nonatomic, strong) NSURLConnection *conn;
//進度條
@property(nonatomic,weak) DACircularProgressView * circleView;
@end
@implementation ViewController
- (void)viewDidLoad{
    [super viewDidLoad];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"didFailWithError");
}
//接收到響應就會調用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    //下載完成後 再次點擊的時候,若是爲1就直接返回,不在下載,或彈框告訴用戶已經存在,
    //須要將self.currentLength寫入本地文件才能作到不會重複下載.就是說這個程序沒法避免重複下載
    if (self.currentLength) return;
    //數據保存的路徑
    NSString * caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString * filepath = [caches stringByAppendingPathComponent:@"download2.mp4"];
    //經過這個路徑建立一個文件  到 沙盒中
    NSFileManager * mgr = [NSFileManager defaultManager];
    [mgr createFileAtPath:filepath contents:nil attributes:nil];
    //建立一個用來寫入文件數據的文件句柄
    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
    //獲取文件總大小
    self.totalLength = response.expectedContentLength;
    NSLog(@"didReceiveResponse文件總大小%lld",self.totalLength);
}
//接受到數據就會調用,若是數據很大會被調用屢次.邊下邊存儲到沙盒,不會有內存問題
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    //移動到文件的最後面
    [self.writeHandle seekToEndOfFile];
    //數據寫入沙盒
    [self.writeHandle writeData:data];
    //累計文件長度,經過循環不斷增大這個值,在下面的方法中拿到這個值量化去下載任務
    //好比這裏第一次拿到300字節,下面請求下載0-300的任務,下次拼接後爲1000,下面請求下載300-1000
    //的任務,
    self.currentLength += data.length;
    self.circleView.progress = (double)self.currentLength / self.totalLength;
    //通過不斷拼接,已經寫入的數據,
    NSLog(@"didReceiveData   已經下載的數據%lld   ",self.currentLength);
}
//下載完成後調用,作些處理工做
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    //變量歸零
    self.currentLength = 1;
    self.totalLength = 0;
    //關閉文佳
    [self.writeHandle closeFile];
    self.writeHandle = nil;
}
- (IBAction)downLoad:(UIButton *)sender{
    //狀態取反
    sender.selected = ! sender.selected;
    //斷點續傳,斷點下載
    if(sender.selected){
        //1.點擊下載,建立URL,發送請求.url中不能有中文
        NSURL * url = [NSURL URLWithString:@"http://localhost/dawenjianyasuo.zip"];
        //2.請求
        NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
        self.currentLength = 0;
        //設置請求頭.實現的要點在這裏,此處的Rang屬性實現了下載的控制,用self.currentLength
        //來保存已經下載了多少字節,
        NSString * range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
        [request setValue:range forHTTPHeaderField:@"Range"];
        //下載(建立完conn對象後,會自動發起一個異步請求)

self.conn = [NSURLConnection connectionWithRequest:request delegate:self]; }else{//一旦點擊暫停建立的request就會銷燬,再次點擊下載時須要從新建立. [self.conn cancel]; self.conn = nil; } } @end

總體流程:框架

原理會在下一篇文章中說明,異步

相關文章
相關標籤/搜索