關於文件下載

###使用xcode自帶的代理方法。xcode

代理方法:
//這個是開始下載時 調用的方法。
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
//這個也是每次都在調用的方法。
data(表明每次下載的數據大小)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

//這個方法是在下載時一直會調用的。這裏有三個參數。
bytesWritten(表明本次下載下載了多少)
totalBytesWritten(表明已經下載了多少)
totalBytesExpectedToWrite(表明文件總大小是多少)
- (void)connection:(NSURLConnection *)connection   didSendBodyData:(NSInteger)bytesWritten
                                                 totalBytesWritten:
(NSInteger)totalBytesWritten
                                         totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;

//這個方法在下載完成後 會自動調用。
connection(這個參數是下完完成後 文件的路徑)
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

1.使用NSUrlContionDownloadDelegate.

1)內存不會暴漲 可是找不到下載完畢以後的文件。 2)能夠直接顯示下載進度。服務器

2.使用NSUrlconnectionDataDelegate.

直接設置NSMutableData屬性來接受下載完畢的數據 . 1)內存依然「暴漲」:至關於仍是先將整個文件下載到內存中 而後在寫入沙盒中 2) 沒法直接顯示下載進度。須要手動計算。session

3.利用NSfileHanddle  

  • NSFileHandle :文件操做句柄,用來拼接文件。
//用已下載的本地路徑去建立handle
 NSFileHandle * handle = [NSFileHandle fileHandleForWritingAtPath:@"/Users/ym/Desktop/haha.zip"];
    //若是handle建立成功 表明本地路徑有文件。
    if (handle) {
        操做句柄到最後
        [handle seekToEndOfFile];
        
        // 拼接文件/寫入文件
        [handle writeData:data];
        
        // 關閉句柄
        [handle closeFile];
       
    }else{
    //本地路徑沒有文件。
就從新建立一個本地文件路徑
        [data writeToFile:@"/Users/ym/Desktop/haha.zip" atomically:YES];

    }

4. NSOutputStream

問題:屢次下載,會直接在以前的文件後拼接文件—>得不到正確的文件數據。app

//首先要根據文件路徑來建立stream 。若是你的這個路徑沒有文件。他會自動給你建立一個文件。atom

   NSOutputStream * stream = [NSOutputStream outputStreamToFileAtPath:@" /Users/ym/Desktop/haha.zip" append:YES];
//建立一個屬性。來存儲文件和關閉stream
    self.stream = stream;
//開啓任務。
    [self.stream open];

//在方法裏 來拼接data內容。
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [self.stream write:data.bytes maxLength:data.length];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
//在下載結束任務後,關閉stream任務。
    [self.stream close];

}

這樣的下載任務。仍是會有和handle同樣的問題。屢次下載和暫停下載以後繼續下載。拼接的文件都是錯誤的。url

因此這裏就引入了斷點續傳功能。代理

###用HEAD請求來獲取下載文件的總大小code

  • HTTP協議方法: HEAD 請求
  • HEAD 請求: 只獲取服務器的響應頭信息,不獲取文件內容(實體內容).
  • 通常在文件下載的時候,提早獲取文件信息.
  • HEAD請求: 和 GET 請求是同樣的.只是不獲取文件內容(實體內容).
//文件路徑
NSString *urlString = @"http://127.0.0.1/music.zip";
    
    NSURL *url = [NSURL URLWithString:urlString];
    //建立請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    // 設置請求方法:
    request.HTTPMethod = @"HEAD";
    
    //  發送 HEAD 請求.
    // HEAD 請求使用什麼方法發送? ---- 通常使用同步方式發送HEAD請求.
    
 NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
    //打印出來的就是你的所須要的文件總大小。
    NSLog(@"response:%zd",response.expectedContentLength);

獲取本地路徑中 文件的大小。

//這裏返回值是一個字典。
 [[NSFileManager defaultManager] attributesOfItemAtPath:self.filePath error:NULL];
//這個就是打印字典的信息。
咱們所須要的就是NSFileSize
**  NSFileCreationDate = "2016-05-05 12:59:14 +0000";
**    NSFileExtensionHidden = 0;
**    NSFileGroupOwnerAccountID = 20;
**    NSFileGroupOwnerAccountName = staff;
**    NSFileModificationDate = "2016-05-05 12:59:17 +0000";
**    NSFileOwnerAccountID = 501;
**    NSFilePosixPermissions = 420;
**    NSFileReferenceCount = 1;
**    NSFileSize = 573278888;
**    NSFileSystemFileNumber = 19578034;
**    NSFileSystemNumber = 16777217;
**    NSFileType = NSFileTypeRegular;

因此要接收這個字典 同時返回NSFileSize.獲取本地文件已經下載的大小。 知道了已經下載的大小,還有總大小。咱們就能夠根據這兩個數值來進行斷點續傳了。orm

斷點續傳須要的請求---Range請求。

設置請求頭信息。 <1>格式: Range格式: bytes = x-y 從x位置開始下載,下載y個字節。 bytes = x- 從x開始 下載到完畢。 bytes = -x 從開始下載x個字節。 <2>特色: 一旦Range 屬性設置成功,相應的狀態碼就是206ip

//startSize 就是上文提到的dict中的NSFileSize。要把這個oc屬性轉化爲字符串。 //bytes=zd - 就是從你斷點的位置下載到文件結束

  NSString *range = [NSString stringWithFormat:@"bytes=%zd-",startSize];
   [request setValue:range forHTTPHeaderField:@"Range"];

下面講一種NSURLSession的下載

  • 利用代理NSURLSessionDownloadDelegate 1.主要利用的代理方法。

  • 這個是每次下載都調用的方法。和上邊的同樣。

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
  • 下載完成以後調用的方法。
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
  • 取消任務。
-(NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
  • 斷點續傳請求。調用上面的方法。
NSString * urlString = @"http://127.0.0.1/music.zip";
    NSURL * url  = [NSURL URLWithString:urlString];
  • 建立可變請求。添加代理。
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
  • 建立下載任務。
    NSURLSessionDownloadTask * task = [session downloadTaskWithURL:url];
    self.oldSession = session;
    self.task = task;
    [task resume];
  • 暫停下載
[self.task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
    self.resumeData = resumeData;
    
}];
  self.task = nil;
  • 繼續下載
if (self.resumeData) {
        self.task = [self.oldSession downloadTaskWithResumeData:self.resumeData];
        [self.task resume];
    }
相關文章
相關標籤/搜索