大文件下載,我們不能像下載小文件那樣直接使用一個(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