zoukankan      html  css  js  c++  java
  • ios开发网络学习三:NSURLConnection小文件大文件下载

    一:小文件下载

    #import "ViewController.h"
    
    @interface ViewController ()<NSURLConnectionDataDelegate>
    /** 注释 */
    @property (nonatomic, strong) NSMutableData *fileData;
    @property (nonatomic, assign) NSInteger totalSize;
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @end
    
    @implementation ViewController
    
    -(NSMutableData *)fileData
    {
        if (_fileData == nil) {
            _fileData = [NSMutableData data];
        }
        return _fileData;
    }
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self download3];
    }
    
    //耗时操作[NSData dataWithContentsOfURL:url]
    -(void)download1
    {
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://img5.imgtn.bdimg.com/it/u=1915764121,2488815998&fm=21&gp=0.jpg"];
        
        //2.下载二进制数据
       NSData *data = [NSData dataWithContentsOfURL:url];
        
        //3.转换
        UIImage *image = [UIImage imageWithData:data];
    }
    
    //1.无法监听进度
    //2.内存飙升
    -(void)download2
    {
        //1.url
       // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
    
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
        
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        //3.发送请求
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
           
            //4.转换
    //        UIImage *image = [UIImage imageWithData:data];
    //        
    //        self.imageView.image = image;
            //NSLog(@"%@",connectionError);
            
            //4.写数据到沙盒中
            NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
            [data writeToFile:fullPath atomically:YES];
        }];
    }
    
    //内存飙升
    -(void)download3
    {
        //1.url
        // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
        
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
        
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        //3.发送请求
        [[NSURLConnection alloc]initWithRequest:request delegate:self];
    }
    
    #pragma mark ----------------------
    #pragma mark NSURLConnectionDataDelegate
    /**
     *  1:当接收到服务器响应的时候调用:只调用一次
     *
     */
    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        NSLog(@"didReceiveResponse");
        
        //得到文件的总大小(本次请求的文件数据的总大小)
        self.totalSize = response.expectedContentLength;
    }
    
    
    /**
     *    2:当下载数据的时候调用,可能被调用多次:在此方法内部有时需要拼接data,也可以在此方法中获得下载的进度
     *
     */
    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
       // NSLog(@"%zd",data.length);
        [self.fileData appendData:data];
        
        //进度=已经下载/文件的总大小
        NSLog(@"%f",1.0 * self.fileData.length /self.totalSize);
    }
    
    /**
     * 3:下载失败的时候的调用
     *
     */
    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
    }
    
    /**
     *    4:下载成功的时候调用
     *
     */
    -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        NSLog(@"connectionDidFinishLoading");
        //4.写数据到沙盒中
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
        
        [self.fileData writeToFile:fullPath atomically:YES];
        NSLog(@"%@",fullPath);
    }
    
    /**
     *    三种方法的区别:1:耗时操作[NSData dataWithContentsOfURL:url]  2:sendAsynchronousRequest,无法监听进度  3:可以进行进度的监听,以及对下载完成后数据的处理
     */
    @end

    (1)第一种方式(NSData)

    ```objc

    //使用NSDta直接加载网络上的url资源(不考虑线程)

    -(void)dataDownload

    {

        //1.确定资源路径

        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"];

        //2.根据URL加载对应的资源

        NSData *data = [NSData dataWithContentsOfURL:url];

        //3.转换并显示数据

        UIImage *image = [UIImage imageWithData:data];

        self.imageView.image = image;

    }

    ```

    (2)第二种方式(NSURLConnection-sendAsync)

    ```objc

    //使用NSURLConnection发送异步请求下载文件资源

    -(void)connectDownload

    {

        //1.确定请求路径

        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"];

        //2.创建请求对象

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        //3.使用NSURLConnection发送一个异步请求

        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

            //4.拿到并处理数据

            UIImage *image = [UIImage imageWithData:data];

            self.imageView.image = image;

        }];

    }

    ```

    (3)第三种方式(NSURLConnection-delegate)

    ```objc

    //使用NSURLConnection设置代理发送异步请求的方式下载文件

    -(void)connectionDelegateDownload

    {

        //1.确定请求路径

        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];

        //2.创建请求对象

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        //3.使用NSURLConnection设置代理并发送异步请求

        [NSURLConnection connectionWithRequest:request delegate:self];

    }

    #pragma mark--NSURLConnectionDataDelegate

    //当接收到服务器响应的时候调用,该方法只会调用一次

    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    {

        //创建一个容器,用来接收服务器返回的数据

        self.fileData = [NSMutableData data];

        //获得当前要下载文件的总大小(通过响应头得到)

        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

        self.totalLength = res.expectedContentLength;

        NSLog(@"%zd",self.totalLength);

        //拿到服务器端推荐的文件名称

        self.fileName = res.suggestedFilename;

    }

    //当接收到服务器返回的数据时会调用

    //该方法可能会被调用多次

    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

    {

    //    NSLog(@"%s",__func__);

        //拼接每次下载的数据

        [self.fileData appendData:data];

        //计算当前下载进度并刷新UI显示

        self.currentLength = self.fileData.length;

        NSLog(@"%f",1.0* self.currentLength/self.totalLength);

        self.progressView.progress = 1.0* self.currentLength/self.totalLength;

    }

    //当网络请求结束之后调用

    -(void)connectionDidFinishLoading:(NSURLConnection *)connection

    {

        //文件下载完毕把接受到的文件数据写入到沙盒中保存

        //1.确定要保存文件的全路径

        //caches文件夹路径

        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

        NSString *fullPath = [caches stringByAppendingPathComponent:self.fileName];

        //2.写数据到文件中

        [self.fileData writeToFile:fullPath atomically:YES];

        NSLog(@"%@",fullPath);

    }

    //当请求失败的时候调用该方法

    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

    {

        NSLog(@"%s",__func__);

    }

    ```

     二:大文件下载

    #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;
    @end
    
    @implementation ViewController
    /**
     * 1:大文件下载的时候,不断的拼接二进制数据,此时会导致内存的飙升,所以此时应该用文件句柄去写文件,创建一个空文件夹,创建文件句柄对象,将下载的文件一点一点拼接到空文件夹内。在文件下载完毕后,要关闭文件句柄,并设为nil空值
     *
     */
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self download3];
    }
    
    //内存飙升
    -(void)download3
    {
        //1.url
        // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
        
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
        
        //2.创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        //3.发送请求
        [[NSURLConnection alloc]initWithRequest:request delegate:self];
    }
    
    #pragma mark ----------------------
    #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:@"123.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
    {
        //1.移动文件句柄到数据的末尾
        [self.handle seekToEndOfFile];
        
        //2.写数据
        [self.handle writeData:data];
        
        //3.获得进度
        self.currentSize += data.length;
        
        //进度=已经下载/文件的总大小
        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.关闭文件句柄
        [self.handle closeFile];
        self.handle = nil;
        
        NSLog(@"connectionDidFinishLoading");
        NSLog(@"%@",self.fullPath);
    }
    @end

    (1)第一种方式(NSData)

    ```objc

    //使用NSDta直接加载网络上的url资源(不考虑线程)

    -(void)dataDownload

    {

        //1.确定资源路径

        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"];

        //2.根据URL加载对应的资源

        NSData *data = [NSData dataWithContentsOfURL:url];

        //3.转换并显示数据

        UIImage *image = [UIImage imageWithData:data];

        self.imageView.image = image;

    }

    ```

    (2)第二种方式(NSURLConnection-sendAsync)

    ```objc

    //使用NSURLConnection发送异步请求下载文件资源

    -(void)connectDownload

    {

        //1.确定请求路径

        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"];

        //2.创建请求对象

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        //3.使用NSURLConnection发送一个异步请求

        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

            //4.拿到并处理数据

            UIImage *image = [UIImage imageWithData:data];

            self.imageView.image = image;

        }];

    }

    ```

    (3)第三种方式(NSURLConnection-delegate)

    ```objc

    //使用NSURLConnection设置代理发送异步请求的方式下载文件

    -(void)connectionDelegateDownload

    {

        //1.确定请求路径

        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];

        //2.创建请求对象

        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        //3.使用NSURLConnection设置代理并发送异步请求

        [NSURLConnection connectionWithRequest:request delegate:self];

    }

    #pragma mark--NSURLConnectionDataDelegate

    //当接收到服务器响应的时候调用,该方法只会调用一次

    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    {

        //创建一个容器,用来接收服务器返回的数据

        self.fileData = [NSMutableData data];

        //获得当前要下载文件的总大小(通过响应头得到)

        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

        self.totalLength = res.expectedContentLength;

        NSLog(@"%zd",self.totalLength);

        //拿到服务器端推荐的文件名称

        self.fileName = res.suggestedFilename;

    }

    //当接收到服务器返回的数据时会调用

    //该方法可能会被调用多次

    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

    {

    //    NSLog(@"%s",__func__);

        //拼接每次下载的数据

        [self.fileData appendData:data];

        //计算当前下载进度并刷新UI显示

        self.currentLength = self.fileData.length;

        NSLog(@"%f",1.0* self.currentLength/self.totalLength);

        self.progressView.progress = 1.0* self.currentLength/self.totalLength;

    }

    //当网络请求结束之后调用

    -(void)connectionDidFinishLoading:(NSURLConnection *)connection

    {

        //文件下载完毕把接受到的文件数据写入到沙盒中保存

        //1.确定要保存文件的全路径

        //caches文件夹路径

        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

        NSString *fullPath = [caches stringByAppendingPathComponent:self.fileName];

        //2.写数据到文件中

        [self.fileData writeToFile:fullPath atomically:YES];

        NSLog(@"%@",fullPath);

    }

    //当请求失败的时候调用该方法

    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

    {

        NSLog(@"%s",__func__);

    }

    ```

    #####5.0  大文件的下载

    (1)实现思路

        边接收数据边写文件以解决内存越来越大的问题

    (2)核心代码

    ```objc

    //当接收到服务器响应的时候调用,该方法只会调用一次

    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    {

        //0.获得当前要下载文件的总大小(通过响应头得到)

        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

        self.totalLength = res.expectedContentLength;

        NSLog(@"%zd",self.totalLength);

        //创建一个新的文件,用来当接收到服务器返回数据的时候往该文件中写入数据

        //1.获取文件管理者

        NSFileManager *manager = [NSFileManager defaultManager];

        //2.拼接文件的全路径

        //caches文件夹路径

        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

        NSString *fullPath = [caches stringByAppendingPathComponent:res.suggestedFilename];

        self.fullPath  = fullPath;

        //3.创建一个空的文件

        [manager createFileAtPath:fullPath contents:nil attributes:nil];

    }

    //当接收到服务器返回的数据时会调用

    //该方法可能会被调用多次

    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

    {

        //1.创建一个用来向文件中写数据的文件句柄

        //注意当下载完成之后,该文件句柄需要关闭,调用closeFile方法

        NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];

        //2.设置写数据的位置(追加)

        [handle seekToEndOfFile];

        //3.写数据

        [handle writeData:data];

        //4.计算当前文件的下载进度

        self.currentLength += data.length;

        NSLog(@"%f",1.0* self.currentLength/self.totalLength);

        self.progressView.progress = 1.0* self.currentLength/self.totalLength;

    }

    ```

  • 相关阅读:
    大数据入门,到底要怎么学习大数据?
    大数据
    将JWT与Spring Security OAuth结合使用
    使用OAuth保护REST API并使用简单的Angular客户端
    自定义Spring Security的身份验证失败处理
    Spring Security方法级别授权使用介绍
    Nginx高并发配置思路(轻松应对1万并发量)
    Spring Security 5中的默认密码编码器
    Spring Boot Security配置教程
    Spring Security在标准登录表单中添加一个额外的字段
  • 原文地址:https://www.cnblogs.com/cqb-learner/p/5861432.html
Copyright © 2011-2022 走看看