項(xiàng)目需求
我們公司項(xiàng)目是APP和硬件相連钮呀,然后通過WI-FI,硬件做sever昨凡,取回硬件里我們想要取回的東西爽醋,所以我選擇用斷點(diǎn)續(xù)傳
- 斷點(diǎn)續(xù)傳就是從文件上次中斷的地方開始重新下載或上傳數(shù)據(jù),而不是從文件開頭便脊。(例如你上次下載到74%蚂四,斷開連接了,重新連接它會從74%開始下載哪痰,不用從頭開始遂赠,較適用于下載大型文件)
- 斷點(diǎn)續(xù)傳主要依賴于HTTP頭部定義的Range來完成的
- 斷點(diǎn)續(xù)傳原理可以查看https://www.ibm.com/developerworks/cn/mobile/mo-cn-breakpoint/index.html 非常簡單明了
我用的斷點(diǎn)續(xù)傳,是網(wǎng)上大多數(shù)人都用的#import "MQLResumeManager.h" 大家可以谷歌一下晌杰,很多都有我就不一一贅述了 跷睦,其實(shí)這篇文章,也只是我自己留著看的肋演,因?yàn)榫W(wǎng)上寫的比我好的挺多的抑诸,我只是想詳細(xì)的研究一下封裝好的代碼
if (downloadedBytes > 0) {
//已經(jīng)下載過烂琴,所以downloadedBytes=12345,Range: bytes=12345”表示請求資源開頭 12345 字節(jié)之后的部分
NSString *requestRange = [NSString stringWithFormat:@"bytes=%llu-", downloadedBytes];
[request setValue:requestRange forHTTPHeaderField:@"Range"];
}else{
//第一次下載沒有已下載數(shù)據(jù)downloadedBytes為空
int fileDescriptor = open([self.targetPath UTF8String], O_CREAT | O_EXCL | O_RDWR, 0666);
if (fileDescriptor > 0) {
close(fileDescriptor);
}
} ```
- 幾個(gè)屬性我們要先搞清楚
```@property (nonatomic, strong) NSURLSession *session; //注意一個(gè)session只能有一個(gè)請求任務(wù)
@property (nonatomic, readwrite, retain) NSError *error; //請求出錯(cuò)
@property (nonatomic, readwrite, copy) completionBlock completionBlock;
@property (nonatomic, readwrite, copy) progressBlock progressBlock;
@property (nonatomic, strong) NSURL *url; //文件資源地址
@property (nonatomic, strong) NSString *targetPath; //文件存放路徑
@property long long totalContentLength; //文件總大小
@property long long totalReceivedContentLength; //已下載大小 ```
``` - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data{
//根據(jù)status code的不同,做相應(yīng)的處理
NSHTTPURLResponse *response = (NSHTTPURLResponse*)dataTask.response;
if (response.statusCode == 200) {
self.totalContentLength = dataTask.countOfBytesExpectedToReceive;
}else if (response.statusCode == 206){
NSString *contentRange = [response.allHeaderFields valueForKey:@"Content-Range"];
if ([contentRange hasPrefix:@"bytes"]) {
//Content-Range: bytes 12367-200000/200000”說明了返回提供了請求資源所在的原始實(shí)體內(nèi)的位置蜕乡,還給出了整個(gè)資源的長度奸绷。
NSArray *bytes = [contentRange componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -/"]];
if ([bytes count] == 4) {
//self.totalCotentLength=200000;
self.totalContentLength = [[bytes objectAtIndex:3] longLongValue];
}
}
}else if (response.statusCode == 416){
NSString *contentRange = [response.allHeaderFields valueForKey:@"Content-Range"];
if ([contentRange hasPrefix:@"bytes"]) {
NSArray *bytes = [contentRange componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" -/"]];
if ([bytes count] == 3) {
self.totalContentLength = [[bytes objectAtIndex:2] longLongValue];
if (self.totalReceivedContentLength == self.totalContentLength) {
//說明已下完
//更新進(jìn)度
self.progressBlock();
}else{
//416 Requested Range Not Satisfiable
self.error = [[NSError alloc]initWithDomain:[self.url absoluteString] code:416 userInfo:response.allHeaderFields];
}
}
}
return;
}else{
//其他情況還沒發(fā)現(xiàn)
return;
}
//向文件追加數(shù)據(jù)
NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:self.targetPath];
[fileHandle seekToEndOfFile]; //將節(jié)點(diǎn)跳到文件的末尾
[fileHandle writeData:data];//追加寫入數(shù)據(jù)
[fileHandle closeFile];
//更新進(jìn)度
self.totalReceivedContentLength += data.length;
self.progressBlock();
}```
- 206 Partial Content 客戶發(fā)送了一個(gè)帶有Range頭的GET請求,服務(wù)器完成了它层玲。
- 416 Requested Range Not Satisfiable 服務(wù)器不能滿足客戶在請求中指定的Range頭号醉。