zoukankan      html  css  js  c++  java
  • iOS开发系列-文件下载

    小文件下载

    NSURLConnection下载小文件

    #import "ViewController.h"
    
    @interface ViewController ()<NSURLConnectionDataDelegate>
    /** 记录文件的总大小 */
    @property (nonatomic, assign) long long totalSize;
    /** 下载的文件名  */
    @property (nonatomic, strong) NSString *fileName;
    /** 已经下载的data */
    @property (nonatomic, strong) NSMutableData *downLoadData;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_04.mp4"];
        NSURLRequest *rquest = [NSURLRequest requestWithURL:url];
        // 发送请求
        [NSURLConnection connectionWithRequest:rquest delegate:self];
        
    }
    
    #pragma mark - NSURLConnectionDataDelegate
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        NSHTTPURLResponse *httpRespone = (NSHTTPURLResponse *)response;
        _totalSize = httpRespone.expectedContentLength; // 获取下载文件的总大小
        _fileName = httpRespone.suggestedFilename; // 下载文件的名
        NSLog(@"%@", httpRespone);
        // 获取响应头字段的value
        // NSString *contentLength = httpRespone.allHeaderFields[@"Content-Length"]; // 也可以获取文件的总长度
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        // 拼接NSData
        [self.downLoadData appendData:data];
        
        // 计算进度
        NSUInteger currLength = self.downLoadData.length;
        double progress = (currLength * 1.0 / self.totalSize) * 100;
        NSLog(@"------------------%@", [NSString stringWithFormat:@"%.2f%%", progress]);
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        // 下载完成将下载的Data写入沙河
        NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
        NSString *filePath = [path stringByAppendingPathComponent:self.fileName];
        [self.downLoadData writeToFile:filePath options:kNilOptions error:nil];
        
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        
    }
    
    @end
    

    NSURLSession下载小文件

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSURL *url = [NSURL URLWithString:@"http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png"];
        // 创建session
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSString *filePath = [FMFILE stringByAppendingPathComponent:response.suggestedFilename];
            [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
        }];
        
        // 执行task
        [task resume];
      
    }
    

    NSURLSessionDownloadTask下载完文件后自动将文件临时存储在沙盒的tmp目录下,通过Block的location返回。我们需要将tmp目录下的文件剪切到要存储的目录下否则系统自动清理。
    这里注意:[NSURL fileURLWithPath:filePath]返回的URL是带有协议头的,而[NSURL URLWithString:@""];返回的是不带协议头的URL。

    因此开发中建议使用NSURLSessionDownloadTask下载小文件。

    大文件下载

    NSURLConnection下载大文件

    大文件的下载不能像小文件下载的方式将服务器每次返回的data拼接到内存。而是需要边下载边写进沙盒,这里需要使用NSFileHander这个类。

    #import "ViewController.h"
    
    #define FMFILE NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject
    
    @interface ViewController ()<NSURLConnectionDataDelegate>
    /** 记录文件的总大小 */
    @property (nonatomic, assign) long long totalLength;
    /** 当前总长度 */
    @property (nonatomic, assign) long long currLength;
    
    @property (nonatomic, strong) NSFileHandle *handle;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_04.mp4"];
        NSURLRequest *rquest = [NSURLRequest requestWithURL:url];
        // 发送请求
        [NSURLConnection connectionWithRequest:rquest delegate:self];
        
    }
    
    #pragma mark - NSURLConnectionDataDelegate
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        // 下载完成将下载的Data写入沙河
        NSHTTPURLResponse *httpRespone = (NSHTTPURLResponse *)response;
        NSString *fileName = httpRespone.suggestedFilename; // 下载文件的名
        NSString *filePath = [FMFILE stringByAppendingPathComponent:fileName];
        
        // 接收到一个响应创建空的文件
        [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
        
        self.totalLength = httpRespone.expectedContentLength; // 获取下载文件的总大小
        
        self.handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
    
        // 每次文件从文件内容尾部拼接
        [self.handle seekToEndOfFile];
        
        // 开始写入数据
        [self.handle writeData:data];
        
        // 拼接总长度
        self.currLength += data.length;
        
        // 计算当前进度
        CGFloat progress = self.currLength * 1.0 / self.totalLength;
        NSLog(@"下载进度----%.2f%%", progress *100);
        
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        [self.handle closeFile];
        self.handle = nil;
        
        // 清零数据
        self.currLength = 0;
        self.totalLength = 0;
    }
    
    @end
    

    NSURLSession下载大文件

    #import "ViewController.h"
    
    #define FMFILE NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject
    @interface ViewController ()<NSURLSessionDownloadDelegate>
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_04.mp4"];
        
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
        
        [task resume];
    }
    
    #pragma mark - NSURLSessionDataDelegate
    /*
     每当写入数据到临时文件就会调用该方法
     bytesWritten 这次写入数据的长度
     totalBytesWritten 已经写入的文件长度
     totalBytesExpectedToWrite 要下载文件的中长度
     */
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
        CGFloat progress = totalBytesWritten * 1.0 / totalBytesExpectedToWrite;
        NSLog(@"----------%.2f%%", progress*100);
    }
    
    /*
     恢复下载
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        
    }
    
    // 现在完毕
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        NSString *filePath = [FMFILE stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
        // 剪切文件
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
    }
    
    // 完成跟失败都会来到这个代理方法
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
        NSLog(@"------------%s", __func__);
    }
    @end
    

    NSURLSession断点下载大文件

    NSURLSession创建的Task的的父类NSURLSessionTask有三个方法,因此它的子类都有这些方法。我们就可以利用这几个方法做断点下载。

    - (void)suspend;
    - (void)resume;
    - (void)cancel;
    
  • 相关阅读:
    LSMW TIPS
    Schedule agreement and Delfor
    Running VL10 in the background 13 Oct
    analyse idoc by creation date
    New Journey Prepare
    EDI error
    CBSN NEWS
    Listen and Write 18th Feb 2019
    Microsoft iSCSI Software Target 快照管理
    通过 Microsoft iSCSI Software Target 提供存储服务
  • 原文地址:https://www.cnblogs.com/CoderHong/p/8896036.html
Copyright © 2011-2022 走看看