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

来源:互联网 发布:office办公软件技巧 编辑:程序博客网 时间:2024/05/16 13:45

小文件下载:

注意: 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
原创粉丝点击