IOS开发入门iOS开发-使用NSURLSession实现文件断点下载,文件离线续传以及图片上传
白羽
2019-05-21
来源 :网络
阅读 486
评论 0
摘要:本文将带你了解IOS开发入门iOS开发-使用NSURLSession实现文件断点下载,文件离线续传以及图片上传,希望本文对大家学IOS有所帮助。
本文将带你了解IOS开发入门iOS开发-使用NSURLSession实现文件断点下载,文件离线续传以及图片上传,希望本文对大家学IOS有所帮助。
NSURLSession
NSURLSession是iOS9.0后苹果推出的网络请求框架,用来代替NSURLConnecttion。使用方法和NSURLConnecttion类似。
NSURLSession使用方法
NSURLSession使用简单,只需使用NSURLSession对象创建Task,然后执行Task即可。NSURLSessionTask是抽象类,不能直接拿来使用,它有两个子类,
NSURLSessionDataTask:用来发起网络请求
-NSURLSessionDataTask的子类,NSURLSessionUploadTask:用来执行上传任务
NSURLSessionDownloadTask:用来执行下载任务
NSURLSession使用范例
1 GET请求:
-(void)get{ //1.确定URL NSURL
*url = [NSURL
URLWithString:@"公司接口"]; //2.创建请求对象 //NSURLRequest
*request =[NSURLRequest
requestWithURL:url]; //3.创建会话对象 NSURLSession
*session = [NSURLSession
sharedSession]; //4.创建Task /* 第一个参数:请求路径 第二个参数:completionHandler
当请求完成之后调用 data:响应体信息 response:响应头信息 error:错误信息当请求失败的时候
error有值 注意:dataTaskWithURL
内部会自动的将请求路径作为参数创建一个请求对象(GET) */ NSURLSessionDataTask
*dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *
_Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable
error)
{ //6.解析数据 NSLog(@"%@",[[NSString
alloc]initWithData:data
encoding:NSUTF8StringEncoding]); }]; //5.执行Task [dataTask
resume];}
2 POST请求:
-(void)post{ //1.确定URL NSURL
*url = [NSURL
URLWithString:@"公司接口"]; //2.创建请求对象 NSMutableURLRequest
*request =[NSMutableURLRequest
requestWithURL:url]; //2.1
设置请求方法为post request.HTTPMethod =
@"POST"; //2.2
设置请求体,POST请求的参数都在这个请求体里,这里只是范例,具体看公司接口文档。 request.HTTPBody
= [@"username=Cehae&pwd=Cehae&type=JSON"
dataUsingEncoding:NSUTF8StringEncoding]; //3.创建会话对象 NSURLSession
*session = [NSURLSession sharedSession]; //4.创建Task /* 第一个参数:请求对象 第二个参数:completionHandler
当请求完成之后调用 !!!
在子线程中调用 data:响应体信息 response:响应头信息 error:错误信息当请求失败的时候
error有值 */ NSURLSessionDataTask
*dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *
_Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable
error)
{ NSLog(@"%@",[NSThread
currentThread]);//注意这里是子线程,请求玩数据需要刷新UI请回到主线程操作 //6.解析数据 NSLog(@"%@",[[NSString
alloc]initWithData:data
encoding:NSUTF8StringEncoding]); }]; //5.执行Task [dataTask
resume];}
3 NSURLSession的代理方法:
@interface
ViewController ()/** 接受响应体信息 */@property
(nonatomic, strong) NSMutableData *fileData;@end @implementation
ViewController -(NSMutableData *)fileData{ if
(_fileData == nil) { _fileData
= [NSMutableData
data]; } return
_fileData;}-(void)touchesBegan:(NSSet*)touches
withEvent:(UIEvent
*)event{ //1.url NSURL *url =
[NSURL URLWithString:@"公司接口"]; //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{ 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.fileData
appendData:data];} /** * 请求结束或者是失败的时候调用 * *
@param session
会话对象 * @param
dataTask
请求任务 * @param
error
错误信息 */-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask
*)task didCompleteWithError:(NSError
*)error{ NSLog(@"%s",__func__); //解析数据 NSLog(@"%@",[[NSString
alloc]initWithData:self.fileData
encoding:NSUTF8StringEncoding]); }
4 NSURLSession和文件句柄实现断点下载
#import
"ViewController.h"#define FileName
@"123.mp4" @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;@property (nonatomic, strong)
NSURLSessionDataTask *dataTask;@property (nonatomic, strong) NSURLSession
*session; @end @implementation
ViewController -(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
小视频url NSURL *url = [NSURL
URLWithString:@"https://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];}
4 NSURLSession实现文件上传
#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:@"https://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:@"https://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);}
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!
本文由 @白羽 发布于职坐标。未经许可,禁止转载。
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢
快给朋友分享吧~
评论(0)