1 interface ViewController () 2 property (weak, nonatomic) IBOutlet UIProgressView *progressView; 3 /** 接收数据的data */ 4 property (nonatomic, strong) NSMutableData *fileData; 6 /*文件名称 */ 7 property (nonatomic, strong) NSString *fileName; 8 property (nonatomic, assign) NSInteger totalSize; 9 end10 implementation ViewController11 -(NSMutableData *)fileData12 {13 if (_fileData nil) {14 _fileData [NSMutableData data];15 }16 return _fileData;17 }18 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event19 {20 //1.确定URL21 NSURL *url [NSURL URLWithString:"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];22 //2.创建请求对象23 NSURLRequest *request [[NSURLRequest alloc]initWithURL:url];24 //3.设置代理,发送请求25 [NSURLConnection connectionWithRequest:request delegate:self];26 }27 #pragma mark - NSURLConnectionDataDelegate28 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response29 {30 //suggestedFilename:服务器端推荐的名称,其实就是url的最后一个节点31 self.fileName response.suggestedFilename;32 //expectedContentLength:获得文件总大小33 34 self.totalSize response.expectedContentLength;35 }36 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data37 {38 //拼接数据39 [self.fileData appendData:data];40 //计算文件的下载进度 已经下载的大小/文件的总大小41 NSLog("%f",1.0 * self.fileData.length /self.totalSize);42 //进度UI43 self.progressView.progress 1.0 * self.fileData.length /self.totalSize;44 }45 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error46 {47 }48 -(void)connectionDidFinishLoading:(NSURLConnection *)connection49 {50 //写数据到磁盘51 NSString *caches [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];52 //拼接全路径53 NSString *fullPath [caches stringByAppendingPathComponent:self.fileName];54 //写沙盒55 [self.fileData writeToFile:fullPath atomically:YES];56 }57 end 大文件下载 NSURLConnection-delegate实现, 实现思路: 边接收数据边写文件以解决内存越来越大的问题
interface ViewController ()property (weak, nonatomic) IBOutlet UIProgressView *progressView;/*文件名称 */property (nonatomic, strong) NSString *fileName;/*文件的总大小*/property (nonatomic, assign) NSInteger totalSize;/*已经下载的文件大小*/property (nonatomic, assign) NSInteger currentSize;/** 文件句柄 */property (nonatomic, strong) NSFileHandle *handle;endimplementation ViewController-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{//1.确定URLNSURL *url [NSURL URLWithString:"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];//2.创建请求对象NSURLRequest *request [[NSURLRequest alloc]initWithURL:url];//3.设置代理,发送请求[NSURLConnection connectionWithRequest:request delegate:self];}#pragma mark - NSURLConnectionDataDelegate//接收到服务器的响应-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{//1.获得caches目录NSString *caches [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];//2.拼接全路径NSString *fullPath [caches stringByAppendingPathComponent:response.suggestedFilename];//3.获得本次请求的文件数据大小(期望大小)self.totalSize response.expectedContentLength;//4.新建一个空的文件/*第一个参数:文件的目录第二个参数:文件的内容第三个参数:文件的属性*/[[NSFileManager defaultManager]createFileAtPath:fullPath contents:nil attributes:nil];//5.创建文件句柄NSFileHandle *handle [NSFileHandle fileHandleForWritingAtPath:fullPath];self.handle handle;}//接收到服务器返回的数据-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{//1.移动文件句柄到文件的末尾 [self.handle seekToEndOfFile];//2.写数据到磁盘 [self.handle writeData:data];//3.计算文件的下载进度 已经下载的大小/文件的总大小self.currentSize data.length;NSLog("%f",1.0 * self.currentSize /self.totalSize);//4.进度UIself.progressView.progress 1.0 * self.currentSize /self.totalSize;}//请求完成-(void)connectionDidFinishLoading:(NSURLConnection *)connection{//释放文件句柄 [self.handle closeFile];self.handle nil;}end 大文件断点下载 实现思路: 设置请求头NSFileHandle 在下载文件的时候不再是整块的从头开始下载而是看当前文件已经下载到哪个地方然后从该地方接着往后面下载。可以通过在请求对象中设置请求头实现。 1.设置请求头,在开始下载的时候设置
//2.创建请求对象 可变的NSMutableURLRequest *request [NSMutableURLRequest requestWithURL:url];//2.1 设置下载文件的某一部分// 只要设置HTTP请求头的Range属性, 就可以实现从指定位置开始下载/*表示头500个字节Range: bytes0-499表示第二个500字节Range: bytes500-999表示最后500个字节Range: bytes-500表示500字节以后的范围Range: bytes500-*/NSString *range [NSString stringWithFormat:"bytes%zd-",self.currentLength];[request setValue:range forHTTPHeaderField:"Range"];
2.注意点下载进度并判断是否需要重新创建文件
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response接收到服务器的响应的方法中代码改动:
//注意点response.expectedContentLength获得是本次请求要下载的文件的大小并非是完整的文件的大小 //文件的总大小 本次要下载的文件大小 已经下载的文件的大小self.totalLength response.expectedContentLength self.currentLength;// 判断当前是否已经下载过如果当前文件已经存在那么直接返回,不然新下载的大小会覆盖原来文件,导致前面文件丢失if (self.currentLength >0) {return;} 大文件输出流下载 使用输出流也可以实现和NSFileHandle相同的功能
//1.创建一个数据输出流/*第一个参数二进制的流数据要写入到哪里第二个参数采用什么样的方式写入流数据如果YES则表示追加如果是NO则表示覆盖*/NSOutputStream *stream [NSOutputStream outputStreamToFileAtPath:fullPath append:YES];//只要调用了该方法就会往文件中写数据//如果文件不存在那么会自动的创建一个 [stream open];self.stream stream;//2.当接收到数据的时候写数据//使用输出流写数据/*第一个参数要写入的二进制数据第二个参数要写入的数据的大小*/[self.stream write:data.bytes maxLength:data.length];//3.当文件下载完毕的时候关闭输出流//关闭输出流 [self.stream close];self.stream nil;
转:https://www.cnblogs.com/liugengqun/p/5136995.html
【感谢龙石数据资产管理和维护 http://www.longshidata.com/pages/government.html】