小文件下载:
注意: Memory 内存会飙升 到48.5MB.当文件下载完后,内存扔不会释放
内容飙升的原因: self.fileData是一个变量.把从网络中的数据保存到了fileData中,并不会释放
// Created by 朝阳 on 2017/12/11.
// Copyright © 2017年 sunny. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic, strong) NSMutableData *fileData;
@property (nonatomic, assign) NSInteger totalSize;
@property (weak, nonatomic) IBOutlet UISlider *slider;
@end
@implementation ViewController
-(NSMutableData *)fileData
{
if (_fileData == nil) {
_fileData = [NSMutableData data];
}
return _fileData;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self download3];
}
//(1)第一种方式(NSData)
//问题: 耗时操作
- (void)download1
{
//1. 确定url
NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1512972458178&di=f9fda7ed145dbd1fa4dfaa799dbeda92&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F7af40ad162d9f2d3467d1a56a3ec8a136327cc1e.jpg"];
//2. 下载二进制数据
NSData *data = [NSData dataWithContentsOfURL:url];
//3. 转换
self.imageView.image = [UIImage imageWithData:data];
}
//(2)第二种方式(NSURLConnection-sendAsync)
//问题1: 无法监听下载进度
//问题2: 内存飙升
- (void)download2
{
//1. 确定请求的url
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos/minion_01.mp4"];
//2. 创建请求
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
//3. 创建异步请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
// 解析数据
// self.imageView.image = [UIImage imageWithData:data];
//4. 写数据到沙盒中
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"1.mp4"];
[data writeToFile:fullPath atomically:YES];
NSLog(@"%@",fullPath);
}];
}
//(3)第三种方式(NSURLConnection-delegate)
//问题: 内存飙升
- (void)download3
{
//1. url
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos/minion_01.mp4"];
//2. 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3. 发送请求(代理)
NSURLConnection *connect = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
#pragma -mark NSURLConnectionDataDelegate
// 当接收到服务器响应的时候调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"didReceiveResponse");
// 得到文件的总大小(本次请求的文件数据的总大小)
self.totalSize = response.expectedContentLength;
}
// 当接收到服务器返回数据的时候调用-并调用多次(数据是一点点返回的)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 拼接服务器中下载的数据 到fileData中
[self.fileData appendData:data];
// 下载进度 = 已经下载 / self.totalSize
NSLog(@"%f",1.0 * self.fileData.length / self.totalSize);
self.slider.value = 1.0 * self.fileData.length / self.totalSize;
}
// 当发送请求失败的时候调用
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%@",error);
}
// 当发送请求完成后调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"connectionDidFinishloading");
//4. 写数据到沙盒中
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"1.mp4"];
[self.fileData writeToFile:fullPath atomically:YES];
NSLog(@"%@",fullPath);
}
@end
大文件下载:
小文件下载时,内容飙升的原因: self.fileData是一个变量.把从网络中的数据保存到了fileData中,并不会释放.
self.fileData在写入到沙盒中,解决内存飙升问题: 直接把数据写入到沙盒中,不通过fileData.
直接写入到沙盒中: 需要使用到两个类: NSFileManager(文件管理者) 和 NSFileHandle(文件句柄)
注意: 这里Memory内存 只是升幅度比较小.
代码:
// Created by 朝阳 on 2017/12/11.
// Copyright © 2017年 sunny. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, assign) NSInteger currentSize;
@property (weak, nonatomic) IBOutlet UISlider *slider;
/** 沙盒路径 */
@property (nonatomic,strong) NSString *fullPath;
/** 文件句柄*/
@property (nonatomic, strong)NSFileHandle *handle;
@end
@implementation ViewController
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self download];
}
// 内容飙升的原因: self.fileData是一个变量. 把从网络中的数据保存到了fileData中,并不会释放
// self.fileData 在写入到沙盒中, 解决内存飙升问题: 直接把数据写入到沙盒中,不通过fileData
- (void)download
{
//1. url
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/MJServer/resources/videos/minion_01.mp4"];
//2. 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3. 发送请求(代理)
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
#pragma -mark NSURLConnectionDataDelegate
// 当接收到服务器响应的时候调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"didReceiveResponse");
//1. 得到文件的总大小(本次请求的文件数据的总大小)
self.totalSize = response.expectedContentLength;
//2. 写数据到沙盒中
self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"1.mp4"];
//3. 创建一个空文件
[[NSFileManager defaultManager] createFileAtPath:self.fullPath contents:nil attributes:nil];
//4. 创建文件句柄(指针)
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
}
// 当接收到服务器返回数据的时候调用-并调用多次(数据是一点点返回的)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 这样直接把数据 写入到沙盒路径中,是不正确的. 会把下载的前面下载的data 给 覆盖掉
//[data writeToFile:self.fullPath atomically:YES];
//1. 移动文件句柄到每次data的末尾
[self.handle seekToEndOfFile];
//2. 写数据
[self.handle writeData:data];
//3. 获得进度
self.currentSize += data.length;
// 下载进度 = 已经下载 / self.totalSize
self.slider.value = 1.0 * self.currentSize / self.totalSize;
NSLog(@"%f",1.0 * self.currentSize / self.totalSize);
}
// 当发送请求失败的时候调用
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%@",error);
}
// 当发送请求完成后调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//1. 关闭文件句柄
[self.handle closeFile];
self.handle = nil;
NSLog(@"connectionDidFinishloading");
NSLog(@"%@",self.fullPath);
}
@end