其实NSURLConnection在iOS7.0之后就逐渐被NSURLSession取代,尤其是iOS9.0出来之后,基本很少有公司再去适配iOS7.0之前的用户了,当然可能,某些比较老旧的项目依然保留着NSURLConnection+NSOperation实现网络请求。就像AFN依旧保留着AFHTTPRequestOperationManager接口。通过
#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || TARGET_WATCH_OS
宏定义,实现跨版本的适配。
那么NSURLConnection和NSURLSession的区别到底在哪呢?
- 异步请求不需要NSOperation包装
- 支持后台运行的网络任务(后台上传下载)
- 根据每个Session做配置,不需要在整个app层面共享配置
- 支持网络操作的取消和断点续传(继承系统类,重写main方法)
- 改进的了授权机制的处理
以下就是通过NSURLConnection实现的文件上传代码,老早之前写的了,因为开发中使用到的地方还是非常少的,除非是遇到AFN上传解决不了的时候,这时候才会去想到回归原生方法去实现上传,比如说上传某些音频文件的时候,有时候AFN就不能完成上传。
注意:
- POST实现⽂文件上传,采⽤用NSURLConnection发送异步请求。
- 调⽤用API需要知参数:
服务器地址(上传文件脚本地址)
服务器允许上传⽂文件key值 ⽂文件名(key)+本地⽂文件路径(value)
服务器允许上传⽂文本⽂文件的key值(key)+⽂文本内容(value)
#import <Foundation/Foundation.h>
@interface XYUploadManager : NSObject
+ (instancetype)sharedXYUploadManager;
//上传文件的API
- (void)postFileToServer:(NSString *)serverUrl serverKey:(NSString *)serverKey fileDict:(NSDictionary *)fileDict paramater:(NSDictionary *)paramater;
//格式化上传数据
- (NSData *)getHttpBodyDataWithServerKey:(NSString *)serverKey fileDict:(NSDictionary *)fileDict;
//格式化上传数据,附带文本信息
- (NSData *)getHttpBodyDataWithServerKey:(NSString *)serverKey fileDict:(NSDictionary *)fileDict paramater:(NSDictionary *)paramater;
@end
//宏定义请求公共字符串
#define kBoundary @"Boundary"
#import "XYUploadManager.h"
@implementation XYUploadManager
/**
* 单例上传文件工具类
*
* @return 实例化单例对象
*/
+ (instancetype)sharedXYUploadManager{
static id _instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
return _instance;
}
/**
* 上传文件API接口
*
* @param serverUrl 请求服务器地址
* @param fileDict 文件名称:fileName(key)= 文件路径filePath(value)
* @param paramater 服务器接收上传文件key = 上传的文本信息value
*/
- (void)postFileToServer:(NSString *)serverUrl serverKey:(NSString *)serverKey fileDict:(NSDictionary *)fileDict paramater:(NSDictionary *)paramater{
NSURL *url = [NSURL URLWithString:serverUrl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",kBoundary];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
request.HTTPBody = [self getHttpBodyDataWithServerKey:serverKey fileDict:fileDict paramater:paramater];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
}];
}
/**
* 格式化上传数据(只有文件信息)
*
* @param serverKey 服务器接受上传文件的key值
* @param fileDict 文件名称:fileName(key)= 文件路径filePath(value)
*
* @return 上传的二进制数据
*/
- (NSData *)getHttpBodyDataWithServerKey:(NSString *)serverKey fileDict:(NSDictionary *)fileDict{
NSMutableData *data = [NSMutableData data];
// 遍历上传参数的数据字典,将上传文件路径和保存的名称都取出来
[fileDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSString *fileName = key;
NSString *filePath = obj;
NSMutableString *headerStr = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBoundary];
[headerStr appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",serverKey,fileName];
// 获取上传文件的类型
NSString *contentType = [self getFileMIMETypeWithFilePath:filePath];
[headerStr appendFormat:@"Content-Type: %@\r\n\r\n",contentType];
// 获取上边界的二进制数据
NSData *headerData = [headerStr dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:headerData];
// 获取上传文件的二进制数据
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[data appendData:fileData];
}];
// 整个上传数据文件的下边界(或每个上传文件都可以有个自己的下边界)
NSMutableString *footerStr = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",kBoundary];
// 获取下边界的二进制数据
NSData *footerData = [footerStr dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:footerData];
return data;
}
/**
* 格式化上传数据(含文本信息)
*
* @param serverKey 服务器接受上传文件的key值
* @param fileDict 文件名称:fileName(key)= 文件路径filePath(value)
* @param paramater 服务器接受文本文件key = 上传的文本信息value
*
* @return 上传文件的二进制数据
*/
- (NSData *)getHttpBodyDataWithServerKey:(NSString *)serverKey fileDict:(NSDictionary *)fileDict paramater:(NSDictionary *)paramater{
NSMutableData *data = [NSMutableData data];
// 遍历上传参数的数据字典,将上传文件路径和保存的名称都取出来
[fileDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSString *fileName = key;
NSString *filePath = obj;
NSMutableString *headerStr = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBoundary];
[headerStr appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",serverKey,fileName];
// 获取上传文件的类型
NSString *contentType = [self getFileMIMETypeWithFilePath:filePath];
[headerStr appendFormat:@"Content-Type: %@\r\n\r\n",contentType];
// 获取上边界的二进制数据
NSData *headerData = [headerStr dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:headerData];
// 获取上传文件的二进制数据
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[data appendData:fileData];
}];
// 文本信息
[paramater enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
// key:服务器接收文本信息的key值
// obj:上传到服务器的文本信息
NSMutableString *headerStr = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBoundary];
[headerStr appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n",key];
NSData *headerData = [headerStr dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:headerData];
NSString *str = obj;
NSData *strData = [str dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:strData];
}];
// 整个上传数据文件的下边界(或每个上传文件都可以有个自己的下边界)
NSMutableString *footerStr = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",kBoundary];
// 获取下边界的二进制数据
NSData *footerData = [footerStr dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:footerData];
return data;
}
/**
* 获取上传文件类型
*
* @param path 本地文件的路径
*
* @return Content-Type
*/
- (NSString *)getFileMIMETypeWithFilePath:(NSString *)path{
// 本地文件的url
NSString *urlStr = [NSString stringWithFormat:@"file://%@",path];
// 中文路径百分号转译
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 定义响应对象,服务器的响应要放在这个响应对象中
NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
// 文件类型:response中的属性
return response.MIMEType;
}
@end