iOS开发网络篇 一一 NSURLConnection-文件下载

小文件下载:

注意: Memory 内存会飙升 到48.5MB.当文件下载完后,内存扔不会释放

内容飙升的原因:  self.fileData是一个变量.把从网络中的数据保存到了fileData中,并不会释放


//  Created by 朝阳 on 2017/12/11.
//  Copyright © 2017年 sunny. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<NSURLConnectionDataDelegate>
@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<UITouch *> *)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 ()<NSURLConnectionDataDelegate>

@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<UITouch *> *)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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

white camel

感谢支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值