ASIHTTPRequest 断点续传

http://code4app.com/ios/Hayate/4fe32cb96803fa6a72000001


一、创建网络请求队列

    首先,创建网络请求队列,如下:

    ASINetworkQueue   *que = [[ASINetworkQueue alloc] init];

    self.netWorkQueue = que;

    [que release];

 

    [self.netWorkQueue reset];

    [self.netWorkQueue setShowAccurateProgress:YES];

    [self.netWorkQueue go];

 

  二、创建存放路径

    //初始化Documents路径

NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

//初始化临时文件路径

NSString *folderPath = [path stringByAppendingPathComponent:@"temp"];

//创建文件管理器

NSFileManager *fileManager = [NSFileManager defaultManager];

//判断temp文件夹是否存在

BOOL fileExists = [fileManager fileExistsAtPath:folderPath];

if (!fileExists) {//如果不存在说创建,因为下载时,不会自动创建文件夹

[fileManager createDirectoryAtPath:folderPath 

               withIntermediateDirectories:YES 

                                attributes:nil

                                     error:nil];

}

        三、发送下载请求

        这里对下面几个对象说明一下:CustomCell是我自定义的cell,cell上面有下载和暂停两个按钮,其tag值为cell所在的行,因此这里的[sendertag]为下载按钮的tag值,self.downloadArray为array数组对象,存放要下载的资源字典信息,在该字典中有一键为URL,它对应的值就是我们下载链接。

   这些东西,根据自己的实际需要改动一下即可使用

    CustomCell *cell = (CustomCell *)[self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:[sender tag] inSection:0]];

    NSString  *filePath = [[self.downloadArray objectAtIndex:[sender tag]] objectForKey:@"URL"];

    NSLog(@"filePath=%@",filePath);

    //初始下载路径

NSURL *url = [NSURL URLWithString:filePath];

//设置下载路径

ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:url];

//设置ASIHTTPRequest代理

request.delegate = self;

    //初始化保存ZIP文件路径

NSString *savePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"book_%d.zip",[sender tag]]];

//初始化临时文件路径

NSString *tempPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"temp/book_%d.zip.temp",[sender tag]]];

//设置文件保存路径

[request setDownloadDestinationPath:savePath];

//设置临时文件路径

[request setTemporaryFileDownloadPath:tempPath];

 

    //设置进度条的代理,

[request setDownloadProgressDelegate:cell];

//设置是是否支持断点下载

[request setAllowResumeForFileDownloads:YES];

//设置基本信息

[request setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:[sender tag]],@"bookID",nil]];

 

    NSLog(@"UserInfo=%@",request.userInfo);

//添加到ASINetworkQueue队列去下载

[self.netWorkQueue addOperation:request];

//收回request

[request release];

    三、暂停请求

    这里的cell下下载时的一样,

CustomCell *cell = (CustomCell *)[self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:[sender tag] inSection:0]];

 

    for (ASIHTTPRequest *request in [self.netWorkQueue operations]) {

        NSInteger bookid = [[request.userInfo objectForKey:@"bookID"] intValue];//查看userinfo信息

        if ([sender tag] == bookid) {//判断ID是否匹配

            //暂停匹配对象

            [request clearDelegatesAndCancel];

        }

    }

 

    四、ASIHTTPRequestDelegate回调方法

          上面已经把下载请求与暂停请求实现,点击下载时,开始下载资源;当点暂停时,下载中断;当我们再点击下载按钮时,继续下载,在第二步的

[request setAllowResumeForFileDownloads:YES]设置是是否支持断点下载。下面要实现ASIHTTPRequestDelegate代理方法如下:

#pragma mark -

#pragma mark ASIHTTPRequestDelegate method

//ASIHTTPRequestDelegate,下载之前获取信息的方法,主要获取下载内容的大小,可以显示下载进度多少字节

- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders {

NSLog(@"didReceiveResponseHeaders-%@",[responseHeaders valueForKey:@"Content-Length"]);

 

    NSLog(@"contentlength=%f",request.contentLength/1024.0/1024.0);

    int bookid = [[request.userInfo objectForKey:@"bookID"] intValue];

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    float tempConLen = [[userDefaults objectForKey:[NSString stringWithFormat:@"book_%d_contentLength",bookid]] floatValue];

    NSLog(@"tempConLen=%f",tempConLen);

    //如果没有保存,则持久化他的内容大小

    if (tempConLen == 0 ) {//如果没有保存,则持久化他的内容大小

        [userDefaults setObject:[NSNumber numberWithFloat:request.contentLength/1024.0/1024.0] forKey:[NSString stringWithFormat:@"book_%d_contentLength",bookid]];

    }

 

}

//ASIHTTPRequestDelegate,下载完成时,执行的方法

- (void)requestFinished:(ASIHTTPRequest *)request {

 

    int bookid = [[request.userInfo objectForKey:@"bookID"] intValue];

    CustomCell *cell = (CustomCell *)[self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:bookid inSection:0]];

    cell.downloadCompleteStatus = YES;

    cell.progressView.progress = 0.0; 

}


    经过上述步骤,一个支持断点续传的功能程序实现了!



HTTP断点续传的基本原理

断点续传是我们现在经常接触的概念,那么HTTP协议是如何支持断点续传的呢。我们先从一个例子来看看。

下面是一个断点续传的例子:(使用Net Vampire得到)

I 01-7-12 19:19:23 ------------------------- Attempt 1 ------------------------- 
P 01-7-12 19:19:24 Connecting to 127.0.0.3 ... 
P 01-7-12 19:19:24 Connected to 127.0.0.3 [127.0.0.3] 
S 01-7-12 19:19:24 GET /VS0515AI.EXE HTTP/1.1 
S 01-7-12 19:19:24 Connection: close 
S 01-7-12 19:19:24 Host: 127.0.0.3 
S 01-7-12 19:19:24 Accept: */* 
S 01-7-12 19:19:24 Pragma: no-cache 
S 01-7-12 19:19:24 Cache-Control: no-cache 
S 01-7-12 19:19:24 Referer: http://127.0.0.3/
S 01-7-12 19:19:24 User-Agent: Mozilla/4.04 [en] (Win95; I ;Nav) 
S 01-7-12 19:19:24 
R 01-7-12 19:19:24 HTTP/1.1 200 OK 
R 01-7-12 19:19:24 Server: Zero Http Server/1.0 
R 01-7-12 19:19:24 Date: Thu, 12 Jul 2001 11:19:24 GMT 
R 01-7-12 19:19:24 Cache-Control: no-cache 
R 01-7-12 19:19:24 Last-Modified: Tue, 30 Jan 2001 13:11:30 GMT 
R 01-7-12 19:19:24 Content-Type: application/octet-stream 
R 01-7-12 19:19:24 Content-Length: 15143086 
R 01-7-12 19:19:24 Connection: close 
R 01-7-12 19:19:24 
P 01-7-12 19:19:25 Data transfer started 
I 01-7-12 19:19:32 Job Stopped by user 
I 01-7-12 19:19:33 Received 5 275 648 bytes in 0:00:07 (691 435 bytes/s)

 

I 01-7-12 19:19:40 ------------------------- Attempt 2 ------------------------- 
P 01-7-12 19:19:40 Connecting to 127.0.0.3 ... 
P 01-7-12 19:19:40 Connected to 127.0.0.3 [127.0.0.3] 
S 01-7-12 19:19:40 GET /VS0515AI.EXE HTTP/1.1 
S 01-7-12 19:19:40 Connection: close 
S 01-7-12 19:19:40 Host: 127.0.0.3 
S 01-7-12 19:19:40 Accept: */* 
S 01-7-12 19:19:40 Pragma: no-cache 
S 01-7-12 19:19:40 Cache-Control: no-cache 
S 01-7-12 19:19:40 Referer: http://127.0.0.3/
S 01-7-12 19:19:40 User-Agent: Mozilla/4.04 [en] (Win95; I ;Nav) 
S 01-7-12 19:19:40 Range: bytes=5275648-
S 01-7-12 19:19:40 
R 01-7-12 19:19:40 HTTP/1.1 206 Partial Content 
R 01-7-12 19:19:40 Server: Zero Http Server/1.0 
R 01-7-12 19:19:40 Date: Thu, 12 Jul 2001 11:19:40 GMT 
R 01-7-12 19:19:40 Cache-Control: no-cache 
R 01-7-12 19:19:40 Last-Modified: Tue, 30 Jan 2001 13:11:30 GMT 
R 01-7-12 19:19:40 Content-Type: application/octet-stream 
R 01-7-12 19:19:40 Content-Range: bytes 5275648-15143085/15143086
R 01-7-12 19:19:40 Content-Length: 9867438
R 01-7-12 19:19:40 Connection: close 
R 01-7-12 19:19:40 
P 01-7-12 19:19:40 Data transfer started 
I 01-7-12 19:19:41 Job Stopped by user 
I 01-7-12 19:19:41 Received 1 124 756 bytes in 0:00:01 (969 617 bytes/s)

 

第一次是普通的传输;第二次由于没有传完全,就发出了Range这个头部,从5275648字节开始传输(默认是按字节算),回应使用206状态值,表示现在开始部分传输,回复Content-Length头部,表示传输的部分,用字节记,然后就与普通传输没有区别了。

 

 

 

NSUrlConnection实现断点续传的关键是自定义http request的头部的range域属性。


 Range头域
  Range头域可以请求实体的一个或者多个子范围。例如,
  表示头500个字节:bytes=0-499
  表示第二个500字节:bytes=500-999
  表示最后500个字节:bytes=-500
  表示500字节以后的范围:bytes=500-
  第一个和最后一个字节:bytes=0-0,-1
  同时指定几个范围:bytes=500-600,601-999
  但是服务器可以忽略此请求头,如果无条件GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200(OK)。


在ios中使用NSMutableURLRequest来定义头部域

  1. NSURL *url1=[NSURL URLWithString:@"下载地址";  
  2. NSMutableURLRequest* request1=[NSMutableURLRequest requestWithURL:url1];  
  3. [request1 setValue:@"bytes=20000-" forHTTPHeaderField:@"Range"];   
  4. [request1 setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];  
  5. NSData *returnData1 = [NSURLConnection sendSynchronousRequest:request1 returningResponse:nil error:nil];   
  6. [self writeToFile:returnData1 fileName:@"SOMEPATH"];  
  7.   
  8.   
  9.   
  10.   
  11. -(void)writeToFile:(NSData *)data fileName:(NSString *) fileName  
  12. {  
  13.     NSString *filePath=[NSString stringWithFormat:@"%@",fileName];  
  14.     if([[NSFileManager defaultManager] fileExistsAtPath:filePath] == NO){  
  15.         NSLog(@"file not exist,create it...");  
  16.         [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];  
  17.     }else {  
  18.     NSLog(@"file exist!!!");  
  19.     }  
  20.   
  21.     FILE *file = fopen([fileName UTF8String], [@"ab+" UTF8String]);  
  22.   
  23.     if(file != NULL){  
  24.         fseek(file, 0, SEEK_END);  
  25.     }  
  26.     int readSize = [data length];  
  27.     fwrite((const void *)[data bytes], readSize, 1, file);  
  28.     fclose(file);  
  29. }  

-------------------------------------------------------------------------------------------------------------------------------------------------------------------


你可能感兴趣的:(ASIHTTPRequest 断点续传)