上传/下载

使用NSURLSession进行上传和下载任务,NSURLSession是iOS7之后推出的,具有downLoadTaskupLoadTask功能,实现任务时,会先将任务挂起,这样可以实现断点续传功能,使用时候要注意resume

下载

  • 最简单的下载
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 1. URL
    NSString *urlString = @"http://192.168.26.201/0805空缺数据 2.xls.zip";
    // 添加 % 转义
    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:urlString];
    
    // NSURLSession,sharedSession是一个全局共享的单例,苹果为了方便程序员使用简单的网络任务
//    NSURLSession *session = [NSURLSession sharedSession];
    
    // 2. 由sharedSession发起网络会话任务
    [[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
        
        NSLog(@"%@", [NSBundle mainBundle].bundlePath);
        NSLog(@"%@", location);
    }] resume];
}
  • 下载解压缩
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSString *urlString = @"http://192.168.26.201/0805空缺数据 2.xls.zip";
    // 添加 % 转义
    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    NSURL *url = [NSURL URLWithString:urlString];
    
    // NSURLSession,sharedSession是一个全局共享的单例,苹果为了方便程序员使用简单的网络任务
    NSURLSession *session = [NSURLSession sharedSession];
    
    // 由session发起下载任务,在URLSession中,所有的任务都是由session发起的
    // 下载任务会保存在tmp文件夹中,如果没有处理,下载的文件会被删除!
    /**
     从网络上下载小说
     
     1. 下载这个小说的zip
     2. 下载完成之后,可以解压缩,原有的zip包就不需要了
     3. URLSession会自动帮我们删除这个zip包
     但是如果调用了这个方法不会调用相应的代理方法,原因不详,望赐教
     */
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
        
        NSLog(@"%@", [NSBundle mainBundle].bundlePath);
        NSLog(@"%@", location);
        
        // 将下载的文件解压缩到cache目录 - 重新启动不会删除
        NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        
        // 解压缩 path属性可以拿到URL中对应的路径
        //使用了解压缩框架ZipArchive
        [SSZipArchive unzipFileAtPath:location.path toDestination:cacheDir];
    }];
    
    // 所有的任务,默认都是挂起的,需要resume
    [task resume];
}
  • 三个代理方法

pragma mark - NSURLSession下载代理方法

1.下载完成

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    //这个操作本身是在异步线程中完成的,如果想要在这个线程中完成下载解压操作,需要在异步线程完成。但是更新UI的操作如collectionView的reloadData要放到主线程去进行
    //如果要在这个方法中使用下载解压操作,要放到
    NSLog(@"下载完成 %@", location);
}

2.断点续传使用

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    // 什么也不写
}

3.下载进度

/**
 bytesWritten                   本次下载的字节数
 totalBytesWritten              已经下载的字节数
 totalBytesExpectedToWrite      下载文件总字节数
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    // 进度 = 已经下载 / 总大小
    float progress = (float)totalBytesWritten / totalBytesExpectedToWrite;
    
    NSLog(@"%f %@", progress, [NSThread currentThread]);
    
    // 主线程更新UI GCD
//    dispatch_async(dispatch_get_main_queue(), ^ { self.progressView.progress = progress;});
    // NSOperation
[[NSOperationQueue mainQueue] addOperationWithBlock: ^ { 
        //进度条
        self.pView.progress = progress;
    }];
}
  • 断点续传
    主要的是关于任务开始和释放
    (注意)

使用下面这个办法注册NSURLSession对象时,需要注意到队列,可以使用主队列,这样下载任务只在主队列进行,使用自己定义的队列或者使用nil的时候,为异步并发队列

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id )delegate delegateQueue:(NSOperationQueue *)queue;

- (NSURLSession *)session
{
    if (_session == nil) {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    }
    return _session;
}

// 开始
- (IBAction)start
{
    self.pView.progress = 0.0f;
    
    // 1. URL
    NSString *urlString = @"http://192.168.26.201/2014苹果发布者大会.mp4";
    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:urlString];
    
    // 2. session
//    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    
    // 3. 下载任务
    self.downloadTask = [self.session downloadTaskWithURL:url];
    [self.downloadTask resume];
}

// 暂停
- (IBAction)pause
{
    // 如果已经暂停,应该不能再一次暂停
    NSLog(@"%s", __func__);
    
    [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
        NSLog(@"====> %zd", resumeData.length);
        // 需要把resumeData保存下来,才能保证后续的续传能够执行
        self.resumeData = resumeData;
        
        // 释放下载任务!
        self.downloadTask = nil;
    }];
}

// 继续
- (IBAction)resume
{
    // 如果已经继续,应该不能再次继续
    if (self.resumeData == nil) {
        // 说明前一次没有被暂停的下载任务
        return;
    }
    
    // 发起续传的网络下载任务
//    [[self.session downloadTaskWithResumeData:self.resumeData] resume];
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    
    // 释放resumeData
    self.resumeData = nil;
    
    [self.downloadTask resume];
}

  • PUT上传、删除文件
@implementation CZViewController
/**
 
 PUT 方法可以上传任意大小的文件
 
 // 设置HTTP请求头属性
 // ****** 注意:不同的网络环境变化,通常都是设置HTTP的请求头字段,通过请求头字段可以告诉服务器很多内容!
 // 譬如:上传文件,授权信息等等,具体如何设置,公司的后端程序员会告诉前端
 
 1. 需要身份验证
 NSString *authStr = @"admin:123456";
 NSString *authBase64 = [@"BASIC " stringByAppendingString:[self base64:authStr]];
 [request setValue:authBase64 forHTTPHeaderField:@"Authorization"];
 
 * DELETE 删除服务器上的文件
 
 request.HTTPMethod = @"DELETE";
 
 身份验证和PUT一致!
 */
// PUT上传
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self putUpload];
}

/** 删除服务器上的文件 Web-DAV */
- (void)deleteFile
{
    // 1. URL 中需要指定PUT上传到服务器上的文件名
    NSURL *url = [NSURL URLWithString:@"http://192.168.26.201/uploads/123.mp4"];
    
    // 2. request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"DELETE";
    
    // 2.1 设置用户名和密码
    NSString *authStr = @"admin:123456";
    // 结果: "BASIC YWRtaW46MTIzNDU2"
    NSString *authBase64 = [@"BASIC " stringByAppendingString:[self base64:authStr]];
    // 设置HTTP请求头属性
    // ****** 注意:不同的网络环境变化,通常都是设置HTTP的请求头字段,通过请求头字段可以告诉服务器很多内容!
    // 譬如:上传文件,授权信息等等,具体如何设置,公司的后端程序员会告诉前端
    [request setValue:authBase64 forHTTPHeaderField:@"Authorization"];
    
    // 3. sesssion 只能使用request进行DELETE删除
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        NSLog(@"完成!");
        
    }] resume];
}

- (void)putUpload
{
    // 1. URL 中需要指定PUT上传到服务器上的文件名
    NSURL *url = [NSURL URLWithString:@"http://192.168.26.201/uploads/123.png"];
    
    // 2. request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"PUT";
    
    // 2.1 设置用户名和密码
    NSString *authStr = @"admin:123456";
    // 结果: "BASIC YWRtaW46MTIzNDU2"
    NSString *authBase64 = [@"BASIC " stringByAppendingString:[self base64:authStr]];
    // 设置HTTP请求头属性
    // ****** 注意:不同的网络环境变化,通常都是设置HTTP的请求头字段,通过请求头字段可以告诉服务器很多内容!
    // 譬如:上传文件,授权信息等等,具体如何设置,公司的后端程序员会告诉前端
    [request setValue:authBase64 forHTTPHeaderField:@"Authorization"];
    
    // 3. sesssion 只能使用request进行PUT上传
    // 参数fromFile -> 本地要上传文件的完成URL
    NSURL *localURL = [[NSBundle mainBundle] URLForResource:@"02.网络应用层次结构.mp4" withExtension:nil];
    
    // 4. 跟踪上传进度
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    
    [[session uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        
        // 提示,跟踪的时候一定不要只输出result
        // 提示:如果是覆盖文件,NSData没有内容
        NSLog(@"====> %@", result);
    }] resume];
}

#pragma mark - 上传文件进度代理方法
/**
 bytesSent                  本次上传字节数
 totalBytesSent             总共上传字节数
 totalBytesExpectedToSend   要上传的字节数
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    float progress = (float)totalBytesSent / totalBytesExpectedToSend;
    
    NSLog(@"%f %@", progress, [NSThread currentThread]);
}

/** 
 将指定的字符串,进行base64编码
 
 BASE64 - 是网络上最常用的编码方式之一(可以编码->看不懂,可以解码->又看的懂了)
 
 BASE64是很多加密算法中的基础算法!
 
 能够达到的效果,将二进制文件转换成ASCII码,从而可以将二进制文件的结果直接当成URL的参数传递
 */
- (NSString *)base64:(NSString *)string
{
    // 1. 将字符串转换成二进制数据
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    
    // 2. 进行base64编码
    return [data base64EncodedStringWithOptions:0];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSLog(@"%@", [self base64:@"admin:123456"]);
}
  • post上传
    用到分类
    链接: http://pan.baidu.com/s/1mgCKndm 密码: ghq4

POST 上传

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 1. URL,是真正负责上传的脚本(php)文件
    NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload.php"];
    
    // 2. request
    /**
     1> 负责上传文件的URL
     2> 上传的文件名:保存在服务器上的文件名称
     3> 本地要上传文件的完整路径
     */
    NSString *localPath = [[NSBundle mainBundle] pathForResource:@"001.png" ofType:nil];
    NSURLRequest *request = [NSMutableURLRequest requestWithUploadURL:url uploadFileName:@"123.png" localFilePath:localPath];
    
    // 3. 上传
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@", result);
    }] resume];
}

你可能感兴趣的:(上传/下载)