iOS网络编程(十)

NSURLSession

使用步骤

使用NSURLSession对象创建Task,然后执行Task


-(void)get

{

//1.确定URL

NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];

//2.创建请求对象

NSURLRequest*request =[NSURLRequestrequestWithURL:url];

//3.创建会话对象

NSURLSession*session = [NSURLSessionsharedSession];

//4.创建Task

/*

第一个参数:请求对象

第二个参数:completionHandler当请求完成之后调用

data:响应体信息

response:响应头信息

error:错误信息当请求失败的时候error有值

*/

NSURLSessionDataTask*dataTask = [sessiondataTaskWithRequest:requestcompletionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullableresponse,NSError*_Nullableerror) {

//6.解析数据

NSLog(@"%@",[[NSStringalloc]initWithData:dataencoding:NSUTF8StringEncoding]);

}];

//5.执行Task

[dataTaskresume];

}

-(void)get2

{

//1.确定URL

NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];

//2.创建请求对象

//NSURLRequest *request =[NSURLRequest requestWithURL:url];

//3.创建会话对象

NSURLSession*session = [NSURLSessionsharedSession];

//4.创建Task

/*

第一个参数:请求路径

第二个参数:completionHandler当请求完成之后调用

data:响应体信息

response:响应头信息

error:错误信息当请求失败的时候error有值

注意:dataTaskWithURL内部会自动的将请求路径作为参数创建一个请求对象(GET)

*/

NSURLSessionDataTask*dataTask = [sessiondataTaskWithURL:urlcompletionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullableresponse,NSError*_Nullableerror) {

//6.解析数据

NSLog(@"%@",[[NSStringalloc]initWithData:dataencoding:NSUTF8StringEncoding]);

}];

//5.执行Task

[dataTaskresume];

}

-(void)post

{

//1.确定URL

NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login"];

//2.创建请求对象

NSMutableURLRequest*request =[NSMutableURLRequestrequestWithURL:url];

//2.1设置请求方法为post

request.HTTPMethod=@"POST";

//2.2设置请求体

request.HTTPBody= [@"username=520it&pwd=520it&type=JSON"dataUsingEncoding:NSUTF8StringEncoding];

//3.创建会话对象

NSURLSession*session = [NSURLSessionsharedSession];

//4.创建Task

/*

第一个参数:请求对象

第二个参数:completionHandler当请求完成之后调用!!!在子线程中调用

data:响应体信息

response:响应头信息

error:错误信息当请求失败的时候error有值

*/

NSURLSessionDataTask*dataTask = [sessiondataTaskWithRequest:requestcompletionHandler:^(NSData*_Nullabledata,NSURLResponse*_Nullableresponse,NSError*_Nullableerror) {

NSLog(@"%@",[NSThreadcurrentThread]);

//6.解析数据

NSLog(@"%@",[[NSStringalloc]initWithData:dataencoding:NSUTF8StringEncoding]);

}];

//5.执行Task

[dataTaskresume];

}


NSURLSession代理方法

#import"ViewController.h"

@interfaceViewController()

/**接受响应体信息*/

@property(nonatomic,strong)NSMutableData*fileData;

@end

@implementationViewController

-(NSMutableData*)fileData

{

if(_fileData==nil) {

_fileData= [NSMutableDatadata];

}

return_fileData;

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event

{

//1.url

NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"];

//2.创建请求对象

NSURLRequest*request = [NSURLRequestrequestWithURL:url];

//3.创建会话对象,设置代理

/*

第一个参数:配置信息[NSURLSessionConfiguration defaultSessionConfiguration]

第二个参数:代理

第三个参数:设置代理方法在哪个线程中调用

*/

NSURLSession*session = [NSURLSessionsessionWithConfiguration:[NSURLSessionConfigurationdefaultSessionConfiguration]delegate:selfdelegateQueue:[NSOperationQueuemainQueue]];

//4.创建Task

NSURLSessionDataTask*dataTask = [sessiondataTaskWithRequest:request];

//5.执行Task

[dataTaskresume];

}

#pragma mark ----------------------

#pragma mark NSURLSessionDataDelegate

/**

*1.接收到服务器的响应它默认会取消该请求

*

*@param session会话对象

*@param dataTask请求任务

*@param response响应头信息

*@param completionHandler回调传给系统

*/

-(void)URLSession:(NSURLSession*)session dataTask:(NSURLSessionDataTask*)dataTask didReceiveResponse:(NSURLResponse*)response completionHandler:(void(^)(NSURLSessionResponseDisposition))completionHandler

{

NSLog(@"%s",__func__);

/*

NSURLSessionResponseCancel = 0,取消默认

NSURLSessionResponseAllow = 1,接收

NSURLSessionResponseBecomeDownload = 2,变成下载任务

NSURLSessionResponseBecomeStream变成流

*/

completionHandler(NSURLSessionResponseAllow);

}

/**

*接收到服务器返回的数据调用多次

*

*@param session会话对象

*@param dataTask请求任务

*@param data本次下载的数据

*/

-(void)URLSession:(NSURLSession*)session dataTask:(NSURLSessionDataTask*)dataTask didReceiveData:(NSData*)data

{

NSLog(@"%s",__func__);

//拼接数据

[self.fileDataappendData:data];

}

/**

*请求结束或者是失败的时候调用

*

*@param session会话对象

*@param dataTask请求任务

*@param error错误信息

*/

-(void)URLSession:(NSURLSession*)session task:(NSURLSessionTask*)task didCompleteWithError:(NSError*)error

{

NSLog(@"%s",__func__);

//解析数据

NSLog(@"%@",[[NSStringalloc]initWithData:self.fileDataencoding:NSUTF8StringEncoding]);

}

@end

NSURLSessionDownloadTask大文件下载(block)

//优点:不需要担心内存

//缺点:无法监听文件下载进度

-(void)download

{

//1.url

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

//2.创建请求对象

NSURLRequest*request = [NSURLRequestrequestWithURL:url];

//3.创建session

NSURLSession*session = [NSURLSessionsharedSession];

//4.创建Task

/*

第一个参数:请求对象

第二个参数:completionHandler回调

location:

response:响应头信息

error:错误信息

*/

//该方法内部已经实现了边接受数据边写沙盒(tmp)的操作

NSURLSessionDownloadTask*downloadTask = [sessiondownloadTaskWithRequest:requestcompletionHandler:^(NSURL*_Nullablelocation,NSURLResponse*_Nullableresponse,NSError*_Nullableerror) {

//6.处理数据

NSLog(@"%@---%@",location,[NSThreadcurrentThread]);

//6.1拼接文件全路径

NSString*fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES)lastObject]stringByAppendingPathComponent:response.suggestedFilename];

//6.2剪切文件

[[NSFileManagerdefaultManager]moveItemAtURL:locationtoURL:[NSURLfileURLWithPath:fullPath]error:nil];

NSLog(@"%@",fullPath);

}];

//5.执行Task

[downloadTaskresume];

}

@end


-(void)delegate

{

//1.url

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

//2.创建请求对象

NSURLRequest *request = [NSURLRequest requestWithURL:url];

//3.创建session

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

//4.创建Task

NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];

//5.执行Task

[downloadTask resume];

}

#pragma mark ----------------------

#pragma mark NSURLSessionDownloadDelegate

/**

*  写数据

*

*  @param session                  会话对象

*  @param downloadTask              下载任务

*  @param bytesWritten              本次写入的数据大小

*  @param totalBytesWritten        下载的数据总大小

*  @param totalBytesExpectedToWrite  文件的总大小

*/

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

{

//1. 获得文件的下载进度

NSLog(@"%f",1.0 * totalBytesWritten/totalBytesExpectedToWrite);

}

/**

*  当恢复下载的时候调用该方法

*

*  @param fileOffset        从什么地方下载

*  @param expectedTotalBytes 文件的总大小

*/

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes

{

NSLog(@"%s",__func__);

}

/**

*  当下载完成的时候调用

*

*  @param location    文件的临时存储路径

*/

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

{

NSLog(@"%@",location);

//1 拼接文件全路径

NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];

//2 剪切文件

[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];

NSLog(@"%@",fullPath);

}

/**

*  请求结束

*/

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

{

NSLog(@"didCompleteWithError");

}

@end

NSURLSessionDownloadTask大文件下载(断点下载)

@interface ViewController ()@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;

@property (nonatomic, strong) NSData *resumData;

@property (nonatomic, strong) NSURLSession *session;

@end

@implementation ViewController

- (IBAction)startBtnClick:(id)sender

{

//1.url

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

//2.创建请求对象

NSURLRequest *request = [NSURLRequest requestWithURL:url];

//3.创建session

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

self.session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

//4.创建Task

NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];

//5.执行Task

[downloadTask resume];

self.downloadTask = downloadTask;

}

//暂停是可以恢复

- (IBAction)suspendBtnClick:(id)sender

{

NSLog(@"+++++++++++++++++++暂停");

[self.downloadTask suspend];

}

//cancel:取消是不能恢复

//cancelByProducingResumeData:是可以恢复

- (IBAction)cancelBtnClick:(id)sender

{

NSLog(@"+++++++++++++++++++取消");

//[self.downloadTask cancel];

//恢复下载的数据!=文件数据

[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {

self.resumData = resumeData;

}];

}

- (IBAction)goOnBtnClick:(id)sender

{

NSLog(@"+++++++++++++++++++恢复下载");

if(self.resumData)

{

self.downloadTask = [self.session downloadTaskWithResumeData:self.resumData];

}

[self.downloadTask resume];

}

//优点:不需要担心内存

//缺点:无法监听文件下载进度

-(void)download

{

//1.url

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

//2.创建请求对象

NSURLRequest *request = [NSURLRequest requestWithURL:url];

//3.创建session

NSURLSession *session = [NSURLSession sharedSession];

//4.创建Task

/*

第一个参数:请求对象

第二个参数:completionHandler 回调

location:

response:响应头信息

error:错误信息

*/

//该方法内部已经实现了边接受数据边写沙盒(tmp)的操作

NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

//6.处理数据

NSLog(@"%@---%@",location,[NSThread currentThread]);

//6.1 拼接文件全路径

NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];

//6.2 剪切文件

[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];

NSLog(@"%@",fullPath);

}];

//5.执行Task

[downloadTask resume];

}

#pragma mark ----------------------

#pragma mark NSURLSessionDownloadDelegate

/**

*  写数据

*

*  @param session                  会话对象

*  @param downloadTask              下载任务

*  @param bytesWritten              本次写入的数据大小

*  @param totalBytesWritten        下载的数据总大小

*  @param totalBytesExpectedToWrite  文件的总大小

*/

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

{

//1. 获得文件的下载进度

NSLog(@"%f",1.0 * totalBytesWritten/totalBytesExpectedToWrite);

}

/**

*  当恢复下载的时候调用该方法

*

*  @param fileOffset        从什么地方下载

*  @param expectedTotalBytes 文件的总大小

*/

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes

{

NSLog(@"%s",__func__);

}

/**

*  当下载完成的时候调用

*

*  @param location    文件的临时存储路径

*/

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

{

NSLog(@"%@",location);

//1 拼接文件全路径

NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];

//2 剪切文件

[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];

NSLog(@"%@",fullPath);

}

/**

*  请求结束

*/

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

{

NSLog(@"didCompleteWithError");

}

@end


使用NSURLSessionDataTask实现大文件下载

#import "ViewController.h"@interface ViewController ()@property (weak, nonatomic) IBOutlet UIProgressView *proessView;/** 接受响应体信息 */@property (nonatomic, strong) NSFileHandle *handle;@property (nonatomic, assign) NSInteger totalSize;@property (nonatomic, assign) NSInteger currentSize;@property (nonatomic, strong) NSString *fullPath;@end@implementation ViewController-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event

{

//1.url

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

//2.创建请求对象

NSURLRequest *request = [NSURLRequest requestWithURL:url];

//3.创建会话对象,设置代理

/*

第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]

第二个参数:代理

第三个参数:设置代理方法在哪个线程中调用

*/

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

//4.创建Task

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];

//5.执行Task

[dataTask resume];

}

#pragma mark ----------------------

#pragma mark NSURLSessionDataDelegate

/**

*  1.接收到服务器的响应 它默认会取消该请求

*

*  @param session          会话对象

*  @param dataTask          请求任务

*  @param response          响应头信息

*  @param completionHandler 回调 传给系统

*/

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler

{

//获得文件的总大小

self.totalSize = response.expectedContentLength;

//获得文件全路径

self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];

//创建空的文件

[[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];

//创建文件句柄

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

[self.handle seekToEndOfFile];

/*

NSURLSessionResponseCancel = 0,取消 默认

NSURLSessionResponseAllow = 1, 接收

NSURLSessionResponseBecomeDownload = 2, 变成下载任务

NSURLSessionResponseBecomeStream        变成流

*/

completionHandler(NSURLSessionResponseAllow);

}

/**

*  接收到服务器返回的数据 调用多次

*

*  @param session          会话对象

*  @param dataTask          请求任务

*  @param data              本次下载的数据

*/

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data

{

//写入数据到文件

[self.handle writeData:data];

//计算文件的下载进度

self.currentSize += data.length;

NSLog(@"%f",1.0 * self.currentSize / self.totalSize);

self.proessView.progress = 1.0 * self.currentSize / self.totalSize;

}

/**

*  请求结束或者是失败的时候调用

*

*  @param session          会话对象

*  @param dataTask          请求任务

*  @param error            错误信息

*/

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

{

NSLog(@"%@",self.fullPath);

//关闭文件句柄

[self.handle closeFile];

self.handle = nil;

}

@end

NSURLSessionDataTask离线断点下载(断点续传)

-(void)viewDidLoad

{

[super viewDidLoad];

//1.读取保存的文件总大小的数据,0

//2.获得当前已经下载的数据的大小

//3.计算得到进度信息

}

-(NSString *)fullPath

{

if (_fullPath == nil) {

//获得文件全路径

_fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:FileName];

}

return _fullPath;

}

-(NSURLSession *)session

{

if (_session == nil) {

//3.创建会话对象,设置代理

/*

第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]

第二个参数:代理

第三个参数:设置代理方法在哪个线程中调用

*/

_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

}

return _session;

}

-(NSURLSessionDataTask *)dataTask

{

if (_dataTask == nil) {

//1.url

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

//2.创建请求对象

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//3 设置请求头信息,告诉服务器请求那一部分数据

self.currentSize = [self getFileSize];

NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];

[request setValue:range forHTTPHeaderField:@"Range"];

//4.创建Task

_dataTask = [self.session dataTaskWithRequest:request];

}

return _dataTask;

}

-(NSInteger)getFileSize

{

//获得指定文件路径对应文件的数据大小

NSDictionary *fileInfoDict = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];

NSLog(@"%@",fileInfoDict);

NSInteger currentSize = [fileInfoDict[@"NSFileSize"] integerValue];

return currentSize;

}

- (IBAction)startBtnClick:(id)sender

{

[self.dataTask resume];

}

- (IBAction)suspendBtnClick:(id)sender

{

NSLog(@"_________________________suspend");

[self.dataTask suspend];

}

//注意:dataTask的取消是不可以恢复的

- (IBAction)cancelBtnClick:(id)sender

{

NSLog(@"_________________________cancel");

[self.dataTask cancel];

self.dataTask = nil;

}

- (IBAction)goOnBtnClick:(id)sender

{

NSLog(@"_________________________resume");

[self.dataTask resume];

}

#pragma mark ----------------------

#pragma mark NSURLSessionDataDelegate

/**

*  1.接收到服务器的响应 它默认会取消该请求

*

*  @param session          会话对象

*  @param dataTask          请求任务

*  @param response          响应头信息

*  @param completionHandler 回调 传给系统

*/

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler

{

//获得文件的总大小

//expectedContentLength 本次请求的数据大小

self.totalSize = response.expectedContentLength + self.currentSize;

if (self.currentSize == 0) {

//创建空的文件

[[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];

}

//创建文件句柄

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

//移动指针

[self.handle seekToEndOfFile];

/*

NSURLSessionResponseCancel = 0,取消 默认

NSURLSessionResponseAllow = 1, 接收

NSURLSessionResponseBecomeDownload = 2, 变成下载任务

NSURLSessionResponseBecomeStream        变成流

*/

completionHandler(NSURLSessionResponseAllow);

}

/**

*  接收到服务器返回的数据 调用多次

*

*  @param session          会话对象

*  @param dataTask          请求任务

*  @param data              本次下载的数据

*/

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data

{

//写入数据到文件

[self.handle writeData:data];

//计算文件的下载进度

self.currentSize += data.length;

NSLog(@"%f",1.0 * self.currentSize / self.totalSize);

self.proessView.progress = 1.0 * self.currentSize / self.totalSize;

}

/**

*  请求结束或者是失败的时候调用

*

*  @param session          会话对象

*  @param dataTask          请求任务

*  @param error            错误信息

*/

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

{

NSLog(@"%@",self.fullPath);

//关闭文件句柄

[self.handle closeFile];

self.handle = nil;

}

-(void)dealloc

{

//清理工作

//finishTasksAndInvalidate

[self.session invalidateAndCancel];

}

@end

(1)关于NSOutputStream的使用

//1. 创建一个输入流,数据追加到文件的屁股上

//把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建

NSOutputStream *stream = [[NSOutputStream alloc]initWithURL:[NSURL fileURLWithPath:[self fullPath]] append:YES];

//2. 打开流

[stream open];

//3. 写入流数据

[stream write:data.bytes maxLength:data.length];

//4.当不需要的时候应该关闭流

[stream close];

(2)关于网络请求请求头的设置(可以设置请求下载文件的某一部分)

//1. 设置请求对象

//1.1 创建请求路径

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

//1.2 创建可变请求对象

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//1.3 拿到当前文件的残留数据大小

self.currentContentLength = [self FileSize];

//1.4 告诉服务器从哪个地方开始下载文件数据

NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentContentLength];

NSLog(@"%@",range);

//1.5 设置请求头

[request setValue:range forHTTPHeaderField:@"Range"];

(3)NSURLSession对象的释放

-(void)dealloc

{

//在最后的时候应该把session释放,以免造成内存泄露

//    NSURLSession设置过代理后,需要在最后(比如控制器销毁的时候)调用session的invalidateAndCancel或者resetWithCompletionHandler,才不会有内存泄露

//    [self.session invalidateAndCancel];

[self.session resetWithCompletionHandler:^{

NSLog(@"释放---");

}];

}

(4)优化部分

01 关于文件下载进度的实时更新

02 方法的独立与抽取

NSURLSession实现文件上传

(1)实现文件上传的方法

/*

第一个参数:请求对象

第二个参数:请求体(要上传的文件数据)

block回调:

NSData:响应体

NSURLResponse:响应头

NSError:请求的错误信息

*/

NSURLSessionUploadTask *uploadTask =  [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error)

(2)设置代理,在代理方法中监听文件上传进度

/*

调用该方法上传文件数据

如果文件数据很大,那么该方法会被调用多次

参数说明:

totalBytesSent:已经上传的文件数据的大小

totalBytesExpectedToSend:文件的总大小

*/

-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend

{

NSLog(@"%.2f",1.0 * totalBytesSent/totalBytesExpectedToSend);

}

(3)关于NSURLSessionConfiguration相关

01 作用:可以统一配置NSURLSession,如请求超时等

02 创建的方式和使用

//创建配置的三种方式

+ (NSURLSessionConfiguration *)defaultSessionConfiguration;

+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;

+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);

//统一配置NSURLSession

-(NSURLSession *)session

{

if (_session == nil) {

//创建NSURLSessionConfiguration

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

//设置请求超时为10秒钟

config.timeoutIntervalForRequest = 10;

//在蜂窝网络情况下是否继续请求(上传或下载)

config.allowsCellularAccess = NO;

_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

}

return _session;

}


#import "ViewController.h"//                  ----WebKitFormBoundaryvMI3CAV0sGUtL8tr#define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx"#define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]@interface ViewController ()/** 注释 */@property (nonatomic, strong) NSURLSession *session;@end

@implementation ViewController

-(NSURLSession *)session

{    

if (_session == nil) {       

 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];                //是否运行蜂窝访问        

config.allowsCellularAccess = YES;       

 config.timeoutIntervalForRequest = 15;                

_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];  

  }    

return _session;

}-

(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event

{

[self upload2];

}

-(void)upload

{

//1.url

NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];

//2.创建请求对象

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//2.1 设置请求方法

request.HTTPMethod = @"POST";

//2.2 设请求头信息

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];

//3.创建会话对象

//    NSURLSession *session = [NSURLSession sharedSession];

//4.创建上传TASK

/*

第一个参数:请求对象

第二个参数:传递是要上传的数据(请求体)

第三个参数:

*/

NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

//6.解析

NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

}];

//5.执行Task

[uploadTask resume];

}

-(void)upload2

{

//1.url

NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];

//2.创建请求对象

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//2.1 设置请求方法

request.HTTPMethod = @"POST";

//2.2 设请求头信息

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"];

//3.创建会话对象

//4.创建上传TASK

/*

第一个参数:请求对象

第二个参数:传递是要上传的数据(请求体)

*/

NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

//6.解析

NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);

}];

//5.执行Task

[uploadTask resume];

}

-(NSData *)getBodyData

{

NSMutableData *fileData = [NSMutableData data];

//5.1 文件参数

/*

--分隔符

Content-Disposition: form-data; name="file"; filename="Snip20160225_341.png"

Content-Type: image/png(MIMEType:大类型/小类型)

空行

文件参数

*/

[fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

//name:file 服务器规定的参数

//filename:Snip20160225_341.png 文件保存到服务器上面的名称

//Content-Type:文件的类型

[fileData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"Sss.png\"" dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

[fileData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

[fileData appendData:KNewLine];

UIImage *image = [UIImage imageNamed:@"Snip20160226_90"];

//UIImage --->NSData

NSData *imageData = UIImagePNGRepresentation(image);

[fileData appendData:imageData];

[fileData appendData:KNewLine];

//5.2 非文件参数

/*

--分隔符

Content-Disposition: form-data; name="username"

空行

123456

*/

[fileData appendData:[[NSString stringWithFormat:@"--%@",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

[fileData appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

[fileData appendData:KNewLine];

[fileData appendData:[@"123456" dataUsingEncoding:NSUTF8StringEncoding]];

[fileData appendData:KNewLine];

//5.3 结尾标识

/*

--分隔符--

*/

[fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];

return fileData;

}

#pragma mark ----------------------

#pragma mark NSURLSessionDataDelegate

/*

*  @param bytesSent                本次发送的数据

*  @param totalBytesSent          上传完成的数据大小

*  @param totalBytesExpectedToSend 文件的总大小

*/

-(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);

}

@end

推荐阅读更多精彩内容