一 创建NSURLSession对象

  • 通过单例获取
@property (class, readonly, strong) NSURLSession *sharedSession;
  • 通过工厂方法获取
// 不用代理
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;// 使用代理
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;

实例代码

// 创建 session 对象
- (void)createSession {// 1.单例NSURLSession *session = [NSURLSession sharedSession];// 2.工厂方法 - 不使用代理NSURLSession *session1 = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];// 3.工厂方法 - 使用代理NSURLSession *session2 = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]delegate:selfdelegateQueue:[NSOperationQueue mainQueue]];
}

在使用自定义方式创建NSURLSession对像时,都需要传入一个NSURLSessionConfiguration参数,这个参数是对Session的网络请求的基本配置。那这个NSURLSessionConfiguration都有哪些配置呢?`

二 NSURLSessionConfiguration详解

有三个方法来创建NSURLSessionConfiguration:

@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;// macos(10.10), ios(8.0), watchos(2.0), tvos(9.0)
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;

解释说明

  • defaultSessionConfiguration 使用全局的cache,cookie,使用硬盘来缓存数据
  • ephemeralSessionConfiguration 临时session配置,与默认配置相比,这个配置不会将缓存、cookie等存在本地,只会存在内存里,所以当程序退出时,所有的数据都会消失
  • backgroundSessionConfigurationWithIdentifier:后台session配置,与默认配置类似,不同的是会在后台开启另一个线程来处理网络数据
    一旦创建了NSURLSessionConfiguration就可以给它设置各种属性

下面对NSURLSessionConfiguration相关属性介绍

@interface NSURLSessionConfiguration : NSObject <NSCopying>/* 三种创建方式 */+ (NSURLSessionConfiguration *)defaultSessionConfiguration;
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);/* 当使用上述第三种方式创建后台sessionConfiguration时可以读到初始化时传入的唯一标识,其他创建方式都为空 */
@property (nullable, readonly, copy) NSString *identifier;/*
缓存策略,默认值是NSURLRequestUseProtocolCachePolicy*/
@property NSURLRequestCachePolicy requestCachePolicy;/* 给request指定每次接收数据超时间隔,如果下一次接受新数据用时超过该值,则发送一个请求超时给该request。默认为60s */
@property NSTimeInterval timeoutIntervalForRequest;/* 给指定resource设定一个超时时间,resource需要在时间到达之前完成。默认是7天。 */
@property NSTimeInterval timeoutIntervalForResource;/* 指定网络传输类型。精切指出传输类型,可以让系统快速响应,提高传输质量,延长电池寿命等。
typedef NS_ENUM(NSUInteger, NSURLRequestNetworkServiceType)
{NSURLNetworkServiceTypeDefault = 0, // 普通网络传输,默认使用这个NSURLNetworkServiceTypeVoIP = 1,    // 网络语音通信传输,只能在VoIP使用NSURLNetworkServiceTypeVideo = 2,   // 影像传输NSURLNetworkServiceTypeBackground = 3, // 网络后台传输,优先级不高时可使用。对用户不需要的网络操作可使用NSURLNetworkServiceTypeVoice = 4       // 语音传输
};*/
@property NSURLRequestNetworkServiceType networkServiceType;/* 是否使用蜂窝网络,默认是yes. */
@property BOOL allowsCellularAccess;/* 是否由系统根据性能自动裁量后台任务。默认值是NO。同sessionSendsLaunchEvent一样,只对后台configuration有效。 */
@property (getter=isDiscretionary) BOOL discretionary NS_AVAILABLE(10_10, 7_0);/*
如果要为app的插件提供session,需要给这个值赋值*/
@property (nullable, copy) NSString *sharedContainerIdentifier NS_AVAILABLE(10_10, 8_0);/* 表示当后台传输结束时,是否启动app.这个属性只对 后台sessionConfiguration 生效,其他configuration类型会自动忽略该值。默认值是YES。*/
@property BOOL sessionSendsLaunchEvents NS_AVAILABLE(NA, 7_0);/*
指定了会话连接中的代理服务器。同样地,大多数面向消费者的应用程序都不需要代理,所以基本上不需要配置这个属性,默认为NULL
*/
@property (nullable, copy) NSDictionary *connectionProxyDictionary;/* 确定是否支持SSLProtocol版本的会话*/
@property SSLProtocol TLSMinimumSupportedProtocol;/*
确定是否支持SSLProtocol版本的会话
*/
@property SSLProtocol TLSMaximumSupportedProtocol;/*
它可以被用于开启HTTP管道,这可以显着降低请求的加载时间,但是由于没有被服务器广泛支持,默认是禁用的*/
@property BOOL HTTPShouldUsePipelining;/*
默认为yes,是否提供来自shareCookieStorge的cookie,如果想要自己提供cookie,可以使用HTTPAdditionalHeaders来提供。*/
@property BOOL HTTPShouldSetCookies;/* Policy for accepting cookies.  This overrides the policy otherwise specified by the cookie storage. */
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;/*
指定了一组默认的可以设置出站请求的数据头。这对于跨会话共享信息,如内容类型,语言,用户代理,身份认证,是很有用的。
例如:@{@"Accept": @"application/json",@"Accept-Language": @"en",@"Authorization": authString,@"User-Agent": userAgentString}*/
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;/*
同时连接一个host的最大数。iOS默认是4.APP是作为一个整体来看的*/
@property NSInteger HTTPMaximumConnectionsPerHost;/*
存储cookie,清除存储,直接set为nil即可。
对于默认和后台的session,使用sharedHTTPCookieStorage。
对于短暂的session,cookie仅仅储存到内存,session失效时会自动清除。*/
@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;/*
证书存储,如果不使用,可set为nil.
默认和后台session,默认使用的sharedCredentialStorage.
短暂的session使用一个私有存储在内存中。session失效会自动清除。*/
@property (nullable, retain) NSURLCredentialStorage *URLCredentialStorage;/*
缓存NSURLRequest的response。
默认的configuration,默认值的是sharedURLCache。
后台的configuration,默认值是nil
短暂的configuration,默认一个私有的cache于内存,session失效,cache自动清除。
*/
@property (nullable, retain) NSURLCache *URLCache;/* Enable extended background idle mode for any tcp sockets created.    Enabling this mode asks the system to keep the socket open*  and delay reclaiming it when the process moves to the background (see https://developer.apple.com/library/ios/technotes/tn2277/_index.html) */
@property BOOL shouldUseExtendedBackgroundIdleMode NS_AVAILABLE(10_11, 9_0);/*
处理NSURLRequest的NSURLProtocol的子类。
重要:对后台Session失效。*/
@property (nullable, copy) NSArray<Class> *protocolClasses;@end

掌握NSURLSessionConfiguration参数,那我们就可以创建一个session对象,然后通过它发送网络请求了。

三 URLSessionTask详解

NSURLSessionTask是一个抽象类,其下有4个实体子类可以直接使用

  • NSURLSessionDataTask
  • NSURLSessionUploadTask
  • NSURLSessionDownloadTask
  • NSURLSessionStreamTask

这四个子类封装了现代程序四个最基本的网络任务:获取数据,比如JSON或者XML,上传文件和下载文件还有数据流的获取。

看看类的声明

  • NSURLSessionDataTask
// NSURLSessionDataTask
@interface NSURLSessionDataTask : NSURLSessionTask
@end
  • NSURLSessionUploadTask
// NSURLSessionUploadTask
@interface NSURLSessionUploadTask : NSURLSessionDataTask
@end
  • NSURLSessionDownloadTask
// NSURLSessionDownloadTask
@interface NSURLSessionDownloadTask : NSURLSessionTask
- (void)cancelByProducingResumeData:(void (^)(NSData * _Nullable resumeData))completionHandler;
@end
  • NSURLSessionStreamTask
@interface NSURLSessionStreamTask : NSURLSessionTask
- (void)readDataOfMinLength:(NSUInteger)minBytes maxLength:(NSUInteger)maxBytes timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSData * _Nullable data, BOOL atEOF, NSError * _Nullable error))completionHandler;- (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSError * _Nullable error))completionHandler;- (void)captureStreams;- (void)closeWrite;- (void)closeRead;- (void)startSecureConnection;- (void)stopSecureConnection;@end

下面是一幅总结图

NSURLSession比NSURLConnection最方便的地方就是任务可以暂停继续。在网络请求中,真正去执行下载或者上传任务的就是URLSessionTask,我们来看一下它常用的方法:

  • - (void)resume;当使用NSURLSession创建一个NSURLSessionTask任务时,要手动调用此方法,任务才会开启,而NSURLConnection默认开启。
  • - (void)suspend;暂停任务方法,手动调用会暂停。当前任务,再次开启此任务时,会从紧接上次任务开始,会面会说到如何暂停任务再开启任务。
  • - (void)cancel;取消任务。

NSURLSessionTask还有一个属性

// The current state of the task within the session.
@property (readonly) NSURLSessionTaskState state;typedef NS_ENUM(NSInteger, NSURLSessionTaskState) {NSURLSessionTaskStateRunning = 0,  /* 正在执行 The task is currently being serviced by the session */NSURLSessionTaskStateSuspended = 1,  // 暂停状态NSURLSessionTaskStateCanceling = 2,  /* 取消状态 The task has been told to cancel.  The session will receive a URLSession:task:didCompleteWithError: message. */NSURLSessionTaskStateCompleted = 3,  /* 任务完成状态 The task has completed and the session will receive no more delegate notifications */
} NS_ENUM_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0);

上面说到的四个类,都直接或间接继承NSURLSessionTask,所有NSURLSessionTask的方法或者属性这四个类都有,接下来详细介绍这四个类。

3.1 NSURLSessionDataTask

NSURLSessionDataTask是开发中使用频率最高的,我们平常使用的GET和POST请求都是通过它来实现的,如果请求的数据简单并且不需要对获取的数据进行复杂操作,我们使用 Block 解析返回的数据即可。具体代码如下:

GET 请求

- (void)sessionDataTaskGet {// 1.请求路径NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/gaoshilist"];// 2.创建请求对象NSURLRequest *request = [NSURLRequest requestWithURL:url];// 3.创建 session 对象NSURLSession *session = [NSURLSession sharedSession];// 4.普通任务 - getNSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse * response, NSError *error) {if (error) {NSLog(@"NSURLSessionDataTaskerror:%@",error);return;}//5.解析数据NSLog(@"NSURLSessionDataTask:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);}];// 启动任务[dataTask resume];
}

运行结果

POST请求

- (void)sessionDataTaskPost {// 1.请求路径NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/fankui"];// 2.创建请求对象NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];// 设置 post 请求方式request.HTTPMethod = @"POST";// 设置请求体request.HTTPBody = [@"username=1234&pwd=4321" dataUsingEncoding:NSUTF8StringEncoding];NSURLSession *session = [NSURLSession sharedSession];NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {if (error) {NSLog(@"NSURLSessionDataTaskerror:%@",error);return;}//5.解析数据NSLog(@"NSURLSessionDataTask:%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);}];[dataTask resume];
}

运行结果

代理实现
另外我们也可以设置session的代理来实时的监听数据

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

它有4个直接或间接的子协议

  • NSURLSessionTaskDelegate
  • NSURLSessionDownloadDelegate
  • NSURLSessionStreamDelegate
  • NSURLSessionDataDelegate

实例代码如下

- (void)sessionDataTaskPostDelegate {// 1.请求路径NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/fankui"];// 2.创建请求对象NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];// 设置 post 请求方式request.HTTPMethod = @"POST";// 设置请求体request.HTTPBody = [@"username=1234&pwd=4321" dataUsingEncoding:NSUTF8StringEncoding];NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];[dataTask resume];
}

NSURLSessionDataDelegate协议方法

// 1.接收到服务器的响应
- (void)URLSession:(NSURLSession *)sessiondataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)responsecompletionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {NSLog(@"didReceiveResponse");// 必须设置对响应进行允许处理才会执行后面两个操作。completionHandler(NSURLSessionResponseAllow);
}// 2.接收到服务器的数据(可能调用多次)
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {NSLog(@"接受到服务器的数据:%lu",data.length);
}// 3.请求成功或者失败(如果失败,error有值)
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {if (error) {NSLog(@"请求失败: %@",error.description);} else {NSLog(@"请求成功");}
}

运行结果如下

3.2 NSURLSessionDownloadTask

NSURLSessionDownloadTask在下载文件的时候,是将数据一点点地写入本地的临时文件。所以在 completionHandler 这个 block 里,我们需要把文件从一个临时地址移动到一个永久的地址保存起来:

实例代码

- (void)sessionDownloadTask {// 1.请求路径NSURL *url = [NSURL URLWithString:@"http://www.pptbz.com/pptpic/UploadFiles_6909/201203/2012031220134655.jpg"];// 2.创建 session 对象NSURLSession *session = [NSURLSession sharedSession];// 下载 taskNSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {// 获取沙盒的 caches 路径NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];// 生成 url 路径NSURL *url = [NSURL fileURLWithPath:path];// 将文件保存到指定文件目录下[[NSFileManager defaultManager] moveItemAtURL:location toURL:url error:nil];NSLog(@"path = %@",path);NSLog(@"%@",[NSThread currentThread]);//切记当前为子线程,dispatch_async(dispatch_get_main_queue(), ^{self.imgView.image = [UIImage imageNamed:path];});}];[task resume];
}

运行结果

通过代理方法下载

#pragma mark - sessionDownloadTaskDelegate- (void)sessionDownloadTaskDelegate {// 1.请求路径
//    NSURL *url = [NSURL URLWithString:@"http://www.pptbz.com/pptpic/UploadFiles_6909/201203/2012031220134655.jpg"];NSURL *url = [NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V5.4.0.dmg"];// 2.创建带有代理方法的自定义 sessionNSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];// 3.创建任务NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];// 4. 开启任务[task resume];
}#pragma mark - NSURLSessionDownloadDelegate/***  写入临时文件时调用*  @param bytesWritten              本次写入大小*  @param totalBytesWritten         已写入文件大小*  @param totalBytesExpectedToWrite 请求的总文件的大小*/
- (void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTaskdidWriteData:(int64_t)bytesWrittentotalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {//可以监听下载的进度CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;NSLog(@"downloadTask %f",progress);
}// 下载完成调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {// location 还是一个临时路径,需要自己挪到需要的路径(caches 文件夹)NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];NSLog(@"downloadTask 移动文件路径");
}

执行结果

3.3 断点续传

在开发中,我们经常由于某种原因,在下载或上传的时候往往不能一次性下载或上传完,有可能下载或上传了一半就终止了,这时候当条件满足继续下载或上传时,我们不希望从头开始,这时候就可以使用断点续传。它的大概思路是:

  • 某种限制,续传暂停
  • 将暂停后数据(当前数据)保存起来–_resumeData = resumeData;
  • 条件允许续传时,使用resumeData创建新的NSURLSessionTask

实例代码如下

/** 进度条*/
@property(nonatomic,strong)UIView *progressView;
/** 进度值*/
@property(nonatomic,strong)UILabel *progressLbe;
/** downloadtask*/
@property(nonatomic,strong)NSURLSessionDownloadTask *downloadTask;
/** data*/
@property(nonatomic,strong)NSData *resumeData;
/** session*/
@property(nonatomic,strong)NSURLSession *session;
  • 下载和取消按钮操作
#pragma mark - 按钮点击// 开始下载
- (void)tapDownload {// 1.URLNSURL *url = [NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V5.4.0.dmg"];if (self.resumeData) {  // 之前已经下载过了self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];} else {self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];NSURLRequest *request = [NSURLRequest requestWithURL:url];self.downloadTask = [self.session downloadTaskWithRequest:request];}[self.downloadTask resume];
}// 暂停下载
- (void)tapSuspend {if (self.downloadTask) {__weak typeof (self)weakSelf = self;[self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {NSLog(@"resumeData:%@",resumeData);weakSelf.resumeData = resumeData;weakSelf.downloadTask = nil;}];}
}// 恢复
- (void)tapRecover {self.downloadTask = nil;self.session = nil;self.resumeData = nil;self.progressLbe.text = @"0";CGRect frame = CGRectMake(0, 0, kScreanWidth * 0.6 * 0, 20);self.progressView.frame = frame;
}
  • NSURLSessionDownloadDelegate
#pragma mark - NSURLSessionDownloadDelegate/***  写入临时文件时调用*  @param bytesWritten              本次写入大小*  @param totalBytesWritten         已写入文件大小*  @param totalBytesExpectedToWrite 请求的总文件的大小*/
- (void)URLSession:(NSURLSession *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTaskdidWriteData:(int64_t)bytesWrittentotalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {//可以监听下载的进度CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;dispatch_async(dispatch_get_main_queue(), ^{self.progressLbe.text = [NSString stringWithFormat:@"%.2f",progress];CGRect frame = CGRectMake(0, 0, kScreanWidth * 0.6 * progress, 20);self.progressView.frame = frame;});
}// 下载完成调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {// location 还是一个临时路径,需要自己挪到需要的路径(caches 文件夹)NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];NSLog(@"downloadTask 移动文件路径");
}

运行结果

3.4 NSURLSessionUploadTask

在 NSURLSession 中,文件上传主要使用五种方式:

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;

下面我们介绍使用uploadTaskWithRequest:fromData表单的形式上传数据

  • 发送请求
// 发送请求
- (void)sessionUploadTask {NSURL *url = [NSURL URLWithString:@"https://api.weibo.com/2/statuses/public_timeline.json"];// 请求NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];// 设置一些参数[request setHTTPMethod:@"POST"];//设置请求体[request setValue:[NSString stringWithFormat: @"multipart/form-data;%@", @"cs"] forHTTPHeaderField:@"Content-type"];//获取上传的图片的dataNSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"picture" ofType:@"jpg"]];//此处添加需要看清楚内容NSData *body =  [self httpFormDataBodyWithBoundary:@"cs" params:@{@"access_token":@"2.00cYYKWF6EKpiB3883361b1dJiZ4eD",@"status":@"哈哈,这是我测试NSURLSession上传文件的微博"} fieldName:@"pic" fileName:@"pic.png" fileContentType:@"image/png" data:data];// 发送请求NSURLSession *session = [NSURLSession sharedSession];NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {if (error) {NSLog(@"error = %@",error.description);} else {NSLog(@"upload  success");}}];[uploadTask resume];
}
  • 拼接请求体
- (NSData *)httpFormDataBodyWithBoundary:(NSString *)boundaryparams:(NSDictionary *)paramsfieldName:(NSString *)fieldNamefileName:(NSString *)fileNamefileContentType:(NSString *)fileContentTypedata:(NSData *)fileData {NSString *preBoundary = [NSString stringWithFormat:@"--%@",boundary];NSString *endBoundary = [NSString stringWithFormat:@"--%@--",boundary];NSMutableString *body = [[NSMutableString alloc] init];//遍历for (NSString *key in params) {//得到当前的key//如果key不是当前的pic,说明value是字符类型,比如name:Boris//添加分界线,换行,必须使用\r\n[body appendFormat:@"%@\r\n",preBoundary];//添加字段名称换2行[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];//添加字段值[body appendFormat:@"%@\r\n",[params objectForKey:key]];}//添加分界线,换行[body appendFormat:@"%@\r\n",preBoundary];//声明pic字段,文件名为boris.png[body appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",fieldName,fileName];//声明上传文件的格式[body appendFormat:@"Content-Type: %@\r\n\r\n",fileContentType];//声明结束符NSString *endStr = [NSString stringWithFormat:@"\r\n%@",endBoundary];//声明myRequestData,用来放入http  bodyNSMutableData *myRequestData = [NSMutableData data];//将body字符串转化为UTF8格式的二进制[myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];//将image的data加入[myRequestData appendData:fileData];//加入结束符--hwg--[myRequestData appendData:[endStr dataUsingEncoding:NSUTF8StringEncoding]];return myRequestData;
}

执行结果

这里我们需要拼接一个表单数据,才能够上传数据。 当然,我们也可以用代理方法来监听上传的进度。


本文参考
NSURLSession与NSURLConnection区别

项目连接地址 - NSURLSessionDemo

更多相关文章参考
iOS-NSURLSession与NSURLConnection区别
iOS-NSURLConnection使用详解


转载自:路飞_Luck

iOS-NSURLSession详解相关推荐

  1. FreeEIM 来点新知识iOS UIScrollView详解

     老程序员FreeEIM 来点新知识iOS UIScrollView详解 UIScrollView 顾名思义也知道这个是和滚动相关的控件,在Android开发时遇到过ScrollView,当内容的 ...

  2. iOS绘图详解-多种绘图方式、裁剪、滤镜、移动、CTM

    iOS绘图详解 摘要: Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎.它提供了低级别.轻量级.高保真度的2D渲染.该框架可以用于基于路径的 绘 ...

  3. IOS UIView详解

    文章目录 IOS UIView详解 1.官方类分析 2. UIView 常用的属性 2.1 UIView的圆角加阴影效果的实现 2.2 UIView 属性 2.2.1 UIView 几何属性 2.2. ...

  4. iOS疯狂详解之AFNetworking图片缓存问题

    AFNetworking网络库已经提供了很好的图片缓存机制,效率是比较高的,但是我发现没有直接提供清除缓存的功能,可项目通常都需要添加 清除功能的功能,因此,在这里我以UIImageView+AFNe ...

  5. iOS多线程详解:实践篇

    iOS多线程实践中,常用的就是子线程执行耗时操作,然后回到主线程刷新UI.在iOS中每个进程启动后都会建立一个主线程(UI线程),这个线程是其他线程的父线程.由于在iOS中除了主线程,其他子线程是独立 ...

  6. iOS疯狂详解之开源库

    youtube下载神器:https://github.com/rg3/youtube-dl vim插件:https://github.com/Valloric/YouCompleteMe vim插件配 ...

  7. [iOS] 国际化详解

    PS:修改设备系统语言方法 设置 -> 通用 -> 语言与地区 -> iPhone 语言 Settings -> General -> Language & Re ...

  8. UE4 IOS打包详解

    写在前面:因为是详解,所以可能写的有可能啰嗦,也有可能有些步骤是你经历过的,那么请忽略它,向下寻找可能的答案,如果没能解决你的问题,那么对此感到很抱歉,没能帮到你,欢迎你给我邮件: bluecode6 ...

  9. iOS模式详解runtime面试工作

    简书:http://www.jianshu.com/p/19f280afcb24 对于从事 iOS 开发人员来说,所有的人都会答出「runtime 是运行时」,什么情况下用runtime?,大部分人能 ...

  10. ios pods 详解

    CocoaPods详解之----使用篇 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/18737437 转载请注明出处 ...

最新文章

  1. 【Python】数据提取xpath和lxml模块(糗事百科的爬虫)
  2. 第十五届全国大学生智能汽车竞赛华东区赛程
  3. ArduinoYun快速入门教程第1章ArduinoYun概览
  4. 限时抢订!价值4800元TechNet Plus赠阅一年!今天己到哈~~~
  5. 利用js实现table增加一行
  6. win10系统下载 Ghost Win10 RS1 1067 64位纯净3月版
  7. ie8不发送ajax,IE8用ajax访问不能每次都刷新的问题
  8. [算法总结] 13 道题搞定 BAT 面试——字符串
  9. from rfc 2068 hypertext怎么解决_“饮水思源”英语怎么翻译
  10. flask v0.1 内部运行程序
  11. Python操作数据库完成接口测试
  12. C盘没W ndows64,win10如何深度清理c盘
  13. 程序员应该阅读的一些书籍
  14. 谷歌gmail注册入口_Google将在今年秋天将所有人推向新版Gmail,无论他们是否愿意...
  15. 【嵌入式06】寄存器方式和HAL库方式实现 串口通信“hello windows!”+流水灯
  16. esp分区引导修复失败_UEFI引导修复教程 win10 MBR无损转GPT分区后修复启动
  17. OpenAI 强化学习 SpiningUP 中文文档 中文教程
  18. C语言编译器和amd兼容吗,Intel的“霸道”:深究编译器对CPU性能的影响
  19. ....他乡遇故知....
  20. 智能家居无线网络体验进入“低容错率”时代,华为Wi-Fi 6如何破局?

热门文章

  1. android 传输视频文件,如何将音视频文件传输到安卓设备中
  2. cifar10案例(cifar10—input.py重点),彩色图片卷积神经网络
  3. linux的rwx权限解读
  4. Kettle XML文件转Excel
  5. vue使用 echarts 3d echarts_esm_echarts__WEBPACK_IMPORTED_MODULE_0__.registerPostInit is not a function
  6. 11.21的自动锁屏 ios_iOS11再现bug 闹铃定时不响 自动锁屏失效
  7. imap收件服务器无响应,imap设置收件服务器
  8. 微信服务号开发者模式下 自定义创建菜单,跳转到其他url
  9. FFmpeg rmvb demuxer中COOK 音频解析
  10. MySQL租户id_查看租户情况