1.大文件下载
-(void)downloadLargeFile{
// 1.创建请求对象
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 2.创建下载任务
/* 参数解释:
第一个参数:设置session的配置信息,一般传默认值
第二个参数:设置代理(遵守NSURLSessionDownloadDelegate协议)
第三个参数:设置代理方法在哪个线程中执行
*/
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
// 3.执行任务
[downloadTask resume];
}
- 控制任务状态
- 注意点: 任务一旦取消, 就不能恢复了
- 如果是调用cancelByProducingResumeData方法, 方法内部会回调一个block, 在block中会将resumeData传递给我们
- resumeData中就保存了当前下载任务的配置信息(下载到什么地方, 从什么地方恢复等等)
-(void)tastState{
[downloadTask cancel];
[downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
}];
[downloadTask suspend];
[session downloadTaskWithResumeData:self.resumeData];
[downloadTask resume];
}
- 监听下载进度(NSURLSessionDownloadDelegate使用)
- 首先控制器需遵守NSURLSessionDownloadDelegate协议
- 在接受数据的代理方法中监听下载数据状况
- 在下载完成后将保存的数据放到应用程序的缓存当中
#pragma mark - NSURLSessionDownloadDelegate
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
}
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
NSLog(@"%s",__func__);
}
2.NSURLsession断点下载功能
- 要想实现断点下载的功能,必须使用二进制任务模式,监听下载进度
- 注意:需要设置请求从上次下载完的地方开始任务
- 另外,代理方法中在获取到服务器响应的代理方法-(void)URLSession:(NSURLSession )session dataTask:(NSURLSessionDataTask )dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler,默认状态时不会接受数据的,必须设置completionHandler的状态为接受模式,才会执行接受数据的代理方法
- 下载完毕后需要关闭输出流
#import "ViewController.h"
#import "NSString+SandboxPath.h"
@interface ViewController ()<NSURLSessionDataDelegate>
@property (nonatomic, assign)NSUInteger totalLength;
@property (nonatomic, assign)NSUInteger currentLength;
@property (nonatomic, strong) NSOutputStream *outputStream ;
@property (nonatomic, copy) NSString *path;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.path = [@"minion_02.mp4" cacheDir];
NSLog(@"%@",self.path);
self.currentLength = [self getFileSizeWithPath:self.path];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *range = [NSString stringWithFormat:@"bytes:%ld-",self.currentLength];
[request setValue:range forHTTPHeaderField:@"Range"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];
}
- (NSUInteger)getFileSizeWithPath:(NSString *)path
{
NSUInteger currentSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil][NSFileSize] integerValue];
return currentSize;
}
#pragma mark - NSURLSessionDataDelegate
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
completionHandler(NSURLSessionResponseAllow);
self.totalLength = response.expectedContentLength + self.currentLength;
NSLog(@"%lld",response.expectedContentLength);
self.outputStream = [NSOutputStream outputStreamToFileAtPath:self.path append:YES];
[self.outputStream open];
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
self.currentLength += data.length;
CGFloat progress = 1.0 * self.currentLength / self.totalLength;
NSLog(@"%lf",progress);
[self.outputStream write:data.bytes maxLength:data.length];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
[self.outputStream close];
}
@end
3.文件上传(基本使用)
- 首先,必须设置请求体格式,要求除了分割线可以随便写以外,其余格式必须完全一模一样才能够上传成功
- 其次,请求体数据拼接好后,不能直接使用request.HTTPBody = body;赋值,也就是说,如果利用NSURLSessionUploadTask上传文件, 那么请求体必须写在fromData参数中, 不能设置在request中
- 如果设置在request中会被忽略
#define ZJBoundary @"MrRight"
#define ZJEncode(string) [string dataUsingEncoding:NSUTF8StringEncoding]
#define ZJNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
-(void)upload{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", ZJBoundary] forHTTPHeaderField:@"Content-Type"];
NSMutableData *body = [NSMutableData data];
[body appendData:ZJEncode(@"--")];
[body appendData:ZJEncode(ZJBoundary)];
[body appendData:ZJNewLine];
[body appendData:ZJEncode([NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"test.png\""])];
[body appendData:ZJNewLine];
[body appendData:ZJEncode([NSString stringWithFormat:@"Content-Type: image/png"])];
[body appendData:ZJNewLine];
[body appendData:ZJNewLine];
[body appendData:[NSData dataWithContentsOfFile:@"/Users/liuzhouji/Desktop/按钮属性.png"]];
[body appendData:ZJNewLine];
[body appendData:ZJEncode(@"--")];
[body appendData:ZJEncode(ZJBoundary)];
[body appendData:ZJEncode(@"--")];
[body appendData:ZJNewLine];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
[task resume];
}
4.断点上传
- 要想实现断点上传功能,创建URL和请求设置和例三一致,只有以下两点不太一样
- 首先设置代理,让当前控制器遵守NSURLSessionTaskDelegate协议
- 实现代理方法监听上传进度
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionUploadTask *task =[session uploadTaskWithRequest:request fromData:body];
[task resume];
#pragma mark - NSURLSessionTaskDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
NSLog(@"%f", 1.0 * totalBytesSent / totalBytesExpectedToSend);
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
NSLog(@"didCompleteWithError");
}