iOS 開發(fā)-NSURLConnection大文件下載解決進(jìn)度以及內(nèi)存增加的問題

大文件下載,我們不能像下載小文件那樣直接使用一個(gè)變量來接受,因?yàn)檫@樣會加載內(nèi)存。所以我們的解決思路應(yīng)該是下載一點(diǎn)數(shù)據(jù)就向文件中寫入一點(diǎn)。另外,在下載過程中暫停下載后,如何做到從某一地方開始繼續(xù)下載,這時(shí)就需要我們在發(fā)請求時(shí),將下載的開始信息包裝到請求頭中。

方式一:使用NSFileHandle創(chuàng)建文件句柄來寫數(shù)據(jù)

#import "ViewController.h"

@interface ViewController ()<NSURLConnectionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;

@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, assign) NSInteger currentSize;
/** 文件句柄*/
@property (nonatomic, strong)NSFileHandle *handle;
/** 沙盒路徑 */
@property (nonatomic, strong) NSString *fullPath;
/** 連接對象 */
@property (nonatomic, strong) NSURLConnection *connect;
@end

@implementation ViewController


- (IBAction)startBtnClick:(id)sender {
    [self download];
}
- (IBAction)cancelBtnClick:(id)sender {
    [self.connect cancel];
}
- (IBAction)goOnBtnClick:(id)sender {
    [self download];
}

//內(nèi)存飆升
-(void)download
{
    //1.url
    NSURL *url = [NSURL URLWithString:@"http://www.33lc.com/article/UploadPic/2012-10/2012102514201759594.jpg"];
    
    //2.創(chuàng)建請求對象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //設(shè)置請求頭信息,告訴服務(wù)器值請求一部分?jǐn)?shù)據(jù)range
    /*
     bytes=0-100 
     bytes=-100
     bytes=0- 請求100之后的所有數(shù)據(jù)
     */
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
    [request setValue:range forHTTPHeaderField:@"Range"];
    NSLog(@"+++++++%@",range);
    
    //3.發(fā)送請求
    NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self];
    self.connect = connect;
}

#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"didReceiveResponse");
    
    //1.得到文件的總大小(本次請求的文件數(shù)據(jù)的總大小 != 文件的總大小)
    // self.totalSize = response.expectedContentLength + self.currentSize;
    
    if (self.currentSize >0) {
        return;
    }
    
    self.totalSize = response.expectedContentLength;
    
    //2.寫數(shù)據(jù)到沙盒中
    self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:response.suggestedFilename];
    
    NSLog(@"%@",self.fullPath);
    
    //3.創(chuàng)建一個(gè)空的文件
    [[NSFileManager defaultManager] createFileAtPath:self.fullPath contents:nil attributes:nil];
    
    //NSDictionary *dict = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
    
    //4.創(chuàng)建文件句柄(指針)
    self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //1.移動(dòng)文件句柄到數(shù)據(jù)的末尾
    [self.handle seekToEndOfFile];
    
    //2.寫數(shù)據(jù)
    [self.handle writeData:data];
    
    //3.獲得進(jìn)度
    self.currentSize += data.length;
    
    //進(jìn)度=已經(jīng)下載/文件的總大小
    NSLog(@"%f",1.0 *  self.currentSize/self.totalSize);
    self.progressView.progress = 1.0 *  self.currentSize/self.totalSize;
    //NSLog(@"%@",self.fullPath);
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //1.關(guān)閉文件句柄
    [self.handle closeFile];
    self.handle = nil;
    
    NSLog(@"connectionDidFinishLoading");
    NSLog(@"%@",self.fullPath);
}
@end

方式二:使用NSOutputStream輸出流來寫數(shù)據(jù)

#import "ViewController.h"

@interface ViewController ()<NSURLConnectionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;

@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, assign) NSInteger currentSize;
/** 沙盒路徑 */
@property (nonatomic, strong) NSString *fullPath;
/** 連接對象 */
@property (nonatomic, strong) NSURLConnection *connect;
/** 輸出流*/
@property (nonatomic, strong) NSOutputStream *stream;
@end

@implementation ViewController


- (IBAction)startBtnClick:(id)sender {
    [self download];
}
- (IBAction)cancelBtnClick:(id)sender {
    [self.connect cancel];
}
- (IBAction)goOnBtnClick:(id)sender {
    [self download];
}

//內(nèi)存飆升
-(void)download
{
    //1.url
    // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
    
    NSURL *url = [NSURL URLWithString:@"http://www.33lc.com/article/UploadPic/2012-10/2012102514201759594.jpg"];
    
    //2.創(chuàng)建請求對象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //設(shè)置請求頭信息,告訴服務(wù)器值請求一部分?jǐn)?shù)據(jù)range
    /*
     bytes=0-100 
     bytes=-100
     bytes=0- 請求100之后的所有數(shù)據(jù)
     */
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
    [request setValue:range forHTTPHeaderField:@"Range"];
    NSLog(@"+++++++%@",range);
    
    //3.發(fā)送請求
    NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self];
    self.connect = connect;
}

#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"didReceiveResponse");
    
    //1.得到文件的總大小(本次請求的文件數(shù)據(jù)的總大小 != 文件的總大小)
    // self.totalSize = response.expectedContentLength + self.currentSize;
    
    if (self.currentSize >0) {
        
        return;
    }
    
    self.totalSize = response.expectedContentLength;
    
    //2.寫數(shù)據(jù)到沙盒中
    self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:response.suggestedFilename];
    
    NSLog(@"%@",self.fullPath);
    //3.創(chuàng)建輸出流
//    NSOutputStream
//    NSInputStream
    /*
     第一個(gè)參數(shù):文件的路徑
     第二個(gè)參數(shù):YES 追加
     特點(diǎn):如果該輸出流指向的地址沒有文件,那么會自動(dòng)創(chuàng)建一個(gè)空的文件
     */
    NSOutputStream *stream = [[NSOutputStream alloc]initToFileAtPath:self.fullPath append:YES];
    
    //打開輸出流
    [stream open];
    self.stream = stream;
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    //寫數(shù)據(jù)
    [self.stream write:data.bytes maxLength:data.length];
    
    //3.獲得進(jìn)度
    self.currentSize += data.length;
    
    //進(jìn)度=已經(jīng)下載/文件的總大小
    NSLog(@"%f",1.0 *  self.currentSize/self.totalSize);
    self.progressView.progress = 1.0 *  self.currentSize/self.totalSize;
    //NSLog(@"%@",self.fullPath);
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    
    //關(guān)閉流
    [self.stream close];
    self.stream = nil;
    
    NSLog(@"connectionDidFinishLoading");
    NSLog(@"%@",self.fullPath);
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 使用NSURLConnection實(shí)現(xiàn)下載 1. 小文件下載 第一種方式(NSData) 第二種方式(NSURLC...
    擱淺的青蛙閱讀 1,979評論 3 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • NSURLSession基本使用 簡介 使用步驟使用NSURLSession會話對象創(chuàng)建Task,然后執(zhí)行Task...
    彼岸的黑色曼陀羅閱讀 1,018評論 0 3
  • NSURLSession 使用步驟使用NSURLSession對象創(chuàng)建Task,然后執(zhí)行Task -(void)g...
    BEYOND黃閱讀 928評論 0 0
  • 朱元璋是正經(jīng)八百地從苦哈哈,一躍而成萬人之上的皇帝。他經(jīng)常以其身世和人生體驗(yàn)訓(xùn)導(dǎo)諸皇子,目的就是讓他們勿忘...
    書漫黃沙閱讀 412評論 0 0