对AFHTTPSessionManager的二次封装,紧贴AFNetworking的思想,先判断在请求,严谨全面,基本满足需求
项目地址:https://github.com/douxindong/XDAFHTTPSessionManager.git
// QQ网络请求讨论群【iOS技术开发帝国】:581443677
参考
// http://www.jianshu.com/p/4b5d2d47833d
// http://www.cnblogs.com/QianChia/p/5768428.html#autoid-7-0-0
效果图:
XDHTTPSessionManager.h
XDHTTPSessionManager.m
XDDownLoadData.h
XDDownLoadData.m
//
// XDHTTPSessionManager.h
// XDAFHTTPSessionManager
//
// Created by 窦心东 on 2016/12/2.
// Copyright © 2016年 窦心东. All rights reserved.
// iOS - HTTPS
// http://www.jianshu.com/p/4b5d2d47833d
// QQ网络请求讨论群【iOS开发帝国Https群】:581443677
// http://www.cnblogs.com/QianChia/p/5768428.html#autoid-7-0-0
#import
#define XDWeak __weak __typeof(self) weakSelf = self
/*! 过期属性或方法名提醒 */
#define XDNetManagerDeprecated(instead) __deprecated_msg(instead)
typedef NS_ENUM(NSUInteger,RequestMethod) {
POST = 0,
GET,
PUT,
PATCH,
DELETE,
HEAD
};
/*!定义请求类型的枚举 */
typedef NS_ENUM(NSUInteger, XDHttpRequestType)
{
/*! get请求 */
XDHttpRequestTypeGet = 0,
/*! post请求 */
XDHttpRequestTypePost,
/*! put请求 */
XDHttpRequestTypePut,
/*! delete请求 */
XDHttpRequestTypeDelete
};
typedef NS_ENUM(NSInteger, AFNetworkErrorType) {
AFNetworkErrorType_TimedOut = NSURLErrorTimedOut, //-1001 请求超时
AFNetworkErrorType_UnURL = NSURLErrorUnsupportedURL, //-1002 不支持的URL
AFNetworkErrorType_NoNetWork = NSURLErrorNotConnectedToInternet, //-1009 断网
AFNetworkErrorType_404Failed = NSURLErrorBadServerResponse, //-1011 404 错误
AFNetworkErrorType_3840Failed = 3840, //3840 请求或者返回不是纯json格式
};
typedef NS_ENUM(NSUInteger, XDNetworkStatus) {
/** 未知网络*/
XDNetworkStatusUnknown,
/** 无网络*/
XDNetworkStatusNotReachable,
/** 手机网络*/
XDNetworkStatusReachableViaWWAN,
/** WIFI网络*/
XDNetworkStatusReachableViaWiFi
};
/** 请求成功的Block */
typedef void(^HttpRequestSuccess)(id responseObject);
/** 请求失败的Block */
typedef void(^HttpRequestFailed)(NSError *error);
/** 缓存的Block */
typedef void(^HttpRequestCache)(id responseCache);
/** 上传或者下载的进度, Progress.completedUnitCount:当前大小 - Progress.totalUnitCount:总大小*/
typedef void (^HttpProgress)(NSProgress *progress);
/** 网络状态的Block*/
typedef void(^NetworkStatus)(XDNetworkStatus status);
/** 请求任务 */
typedef NSURLSessionTask XDURLSessionTask;
#pragma mark - 网络数据请求类
@interface XDHTTPSessionManager : NSObject
/**
* 声明单例方法
*/
+(instancetype)shareManager;
/**
* 开始监听网络状态
*/
+ (void)startMonitoringNetwork;
/**
* 实时获取网络状态回调
*/
+ (void)networkStatusWithBlock:(NetworkStatus)status;
/**
* GET请求,无缓存
*
* @param URL 请求地址
* @param parameters 请求参数
* @param progress 进度信息
* @param success 请求成功的回调
* @param failure 请求失败的回调
*
* @return 返回的对象可取消请求,调用cancle方法
*/
+ (XDURLSessionTask *)GET:(NSString *)URL parameters:(NSDictionary *)parameters progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure;
/**
* GET请求,自动缓存
*
* @param URL 请求地址
* @param parameters 请求参数
* @param responseCache 缓存数据的回调
* @param progress 进度信息
* @param success 请求成功的回调
* @param failure 请求失败的回调
*
* @return 返回的对象可取消请求,调用cancle方法
*/
+ (XDURLSessionTask *)GET:(NSString *)URL parameters:(NSDictionary *)parameters responseCache:(HttpRequestCache)responseCache progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure;
/**
* POST请求,无缓存
*
* @param URL 请求地址
* @param parameters 请求参数
* @param progress 进度信息
* @param success 请求成功的回调
* @param failure 请求失败的回调
*
* @return 返回的对象可取消请求,调用cancle方法
*/
+ (XDURLSessionTask *)POST:(NSString *)URL parameters:(NSDictionary *)parameters progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure;
/**
* POST请求,自动缓存
*
* @param URL 请求地址
* @param parameters 请求参数
* @param responseCache 缓存数据的回调
* @param progress 进度信息
* @param success 请求成功的回调
* @param failure 请求失败的回调
*
* @return 返回的对象可取消请求,调用cancle方法
*/
+ (XDURLSessionTask *)POST:(NSString *)URL parameters:(NSDictionary *)parameters responseCache:(HttpRequestCache)responseCache progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure;
/*!
* 网络请求的实例方法
*
* @param type get / post / put / delete
* @param urlString 请求的地址
* @param parameters 请求的参数
* @param successBlock 请求成功的回调
* @param failureBlock 请求失败的回调
* @param progress 进度
*/
+ (XDURLSessionTask *)ba_requestWithType:(XDHttpRequestType)type UrlString:(NSString *)urlString Parameters:(NSDictionary *)parameters progress:(HttpProgress)progress SuccessBlock:(HttpRequestSuccess)successBlock FailureBlock:(HttpRequestFailed)failureBlock XDNetManagerDeprecated("该方法已过期,请使用最新方法:+ (BAURLSessionTask *)ba_requestWithType:(BAHttpRequestType)type urlString:(NSString *)urlString parameters:(NSDictionary *)parameters successBlock:(BAResponseSuccess)successBlock failureBlock:(BAResponseFail)failureBlock progress:(BADownloadProgress)progress");
/**
* 上传图片文件
*
* @param URL 请求地址
* @param parameters 请求参数
* @param images 图片数组
* @param name 文件对应服务器上的字段
* @param fileName 文件名
* @param mimeType 图片文件的类型,例:png、jpeg(默认类型)....
* @param progress 上传进度信息
* @param success 请求成功的回调
* @param failure 请求失败的回调
*
* @return 返回的对象可取消请求,调用cancle方法
*/
+ (XDURLSessionTask *)uploadWithURL:(NSString *)URL parameters:(NSDictionary *)parameters images:(NSArray *)images name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure;
/**
* 下载文件
*
* @param URL 请求地址
* @param fileDir 文件存储目录(默认存储目录为Download)
* @param progress 文件下载的进度信息
* @param success 下载成功的回调(回调参数filePath:文件的路径)
* @param failure 下载失败的回调
*
* @return 返回NSURLSessionDownloadTask实例,可用于暂停继续,暂停调用suspend方法,开始下载调用resume方法
*/
+ (XDURLSessionTask *)downloadWithURL:(NSString *)URL fileDir:(NSString *)fileDir progress:(HttpProgress)progress success:(void(^)(NSString *filePath))success failure:(HttpRequestFailed)failure;
@end
//
// XDHTTPSessionManager.m
// XDAFHTTPSessionManager
//
// Created by 窦心东 on 2016/12/2.
// Copyright © 2016年 窦心东. All rights reserved.
//
#import "XDHTTPSessionManager.h"
#import "XDNetWorkingCacheManager.h"
#ifdef DEBUG
#define XDLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define XDLog(...)
#endif
static NSMutableArray *tasks;
static XDHTTPSessionManager *XDSessionManager= nil;
static NetworkStatus _status;
@implementation XDHTTPSessionManager
#pragma mark - 实现声明单例方法 GCD
+(instancetype)shareManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
XDSessionManager = [[XDHTTPSessionManager alloc]init];
});
return XDSessionManager;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
XDSessionManager = [super allocWithZone:zone];
});
return XDSessionManager;
}
+ (instancetype)init {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
XDSessionManager = [super init];
[self startMonitoringNetwork];
});
return XDSessionManager;
}
#pragma mark - 设置AFHTTPSessionManager相关属性
+ (AFHTTPSessionManager *)createAFHTTPSessionManager
{
static AFHTTPSessionManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [AFHTTPSessionManager manager];
//设置请求参数的类型:HTTP (AFJSONRequestSerializer,AFHTTPRequestSerializer)
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
//设置请求的超时时间
manager.requestSerializer.timeoutInterval = 30.f;
//设置服务器返回结果的类型:JSON (AFJSONResponseSerializer,AFHTTPResponseSerializer)
manager.responseSerializer = [AFJSONResponseSerializer serializer];
/**
* 请求队列的最大并发数
*/
// manager.operationQueue.maxConcurrentOperationCount = 5;
/*! 打开状态栏的等待菊花 */
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
/*! 设置相应的缓存策略:此处选择不用加载也可以使用自动缓存【注:只有get方法才能用此缓存策略,NSURLRequestReturnCacheDataDontLoad】 */
manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
/*! 设置返回数据类型为 json, 分别设置请求以及相应的序列化器 */
/*!
根据服务器的设定不同还可以设置:
json:[AFJSONResponseSerializer serializer](常用)
http:[AFHTTPResponseSerializer serializer]
*/
AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];
/*! 这里是去掉了键值对里空对象的键值 */
response.removesKeysWithNullValues = YES;
manager.responseSerializer = response;
/* 设置请求服务器数类型式为 json */
/*! 根据服务器的设定不同还可以设置 [AFJSONRequestSerializer serializer](常用) */
AFJSONRequestSerializer *request = [AFJSONRequestSerializer serializer];
manager.requestSerializer = request;
/*! 设置apikey ------类似于自己应用中的tokken---此处仅仅作为测试使用*/
// [manager.requestSerializer setValue:apikey forHTTPHeaderField:@"apikey"];
/*! 复杂的参数类型 需要使用json传值-设置请求内容的类型*/
// [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
/*! 设置响应数据的基本类型 */
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/css",@"text/xml",@"text/plain", @"application/javascript", @"image/*", nil];
/*! https 参数配置 */
/*!
采用默认的defaultPolicy就可以了. AFN默认的securityPolicy就是它, 不必另写代码. AFSecurityPolicy类中会调用苹果security.framework的机制去自行验证本次请求服务端放回的证书是否是经过正规签名.
*/
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
securityPolicy.allowInvalidCertificates = YES;
securityPolicy.validatesDomainName = NO;
manager.securityPolicy = securityPolicy;
/*! 自定义的CA证书配置如下: */
/*! 自定义security policy, 先前确保你的自定义CA证书已放入工程Bundle */
/*!
https://api.github.com网址的证书实际上是正规CADigiCert签发的, 这里把Charles的CA根证书导入系统并设为信任后, 把Charles设为该网址的SSL Proxy (相当于"中间人"), 这样通过代理访问服务器返回将是由Charles伪CA签发的证书.
*/
// NSSet *cerSet = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
// AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
// policy.allowInvalidCertificates = YES;
// manager.securityPolicy = policy;
/*! 如果服务端使用的是正规CA签发的证书, 那么以下几行就可去掉: */
// NSSet *cerSet = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
// AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
// policy.allowInvalidCertificates = YES;
// manager.securityPolicy = policy;
});
return manager;
}
#pragma mark - 开始监听网络
+ (void)startMonitoringNetwork
{
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status)
{
case AFNetworkReachabilityStatusUnknown:
_status(XDNetworkStatusUnknown);
XDLog(@"未知网络");
break;
case AFNetworkReachabilityStatusNotReachable:
_status(XDNetworkStatusNotReachable);
XDLog(@"无网络");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
_status(XDNetworkStatusReachableViaWWAN);
XDLog(@"手机自带网络");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
_status(XDNetworkStatusReachableViaWiFi);
XDLog(@"WIFI");
break;
}
}];
[manager startMonitoring];
}
+ (void)networkStatusWithBlock:(NetworkStatus)status
{
_status = status;
}
#pragma mark - GET请求无缓存
+ (XDURLSessionTask *)GET:(NSString *)URL parameters:(NSDictionary *)parameters progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager GET:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
progress ? progress(uploadProgress) : nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success?success(responseObject):nil;
XDLog(@"responseObject = %@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
failure ? failure(error) : nil;
XDLog(@"error = %@",error);
}];
}
#pragma mark - GET请求自动缓存
+ (XDURLSessionTask *)GET:(NSString *)URL parameters:(NSDictionary *)parameters responseCache:(HttpRequestCache)responseCache progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//读取缓存
responseCache?responseCache([XDNetWorkingCacheManager getResponseCacheForKey:URL]):nil;
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager GET:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
progress ? progress(uploadProgress) : nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success?success(responseObject):nil;
//对数据进行异步缓存
[XDNetWorkingCacheManager saveResponseCache:responseObject forKey:URL];
XDLog(@"responseObject = %@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
failure ? failure(error) : nil;
XDLog(@"error = %@",error);
}];
}
#pragma mark - POST请求无缓存
+ (XDURLSessionTask *)POST:(NSString *)URL parameters:(NSDictionary *)parameters progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager POST:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
progress ? progress(uploadProgress) : nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success?success(responseObject):nil;
XDLog(@"responseObject = %@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
failure ? failure(error) : nil;
XDLog(@"error = %@",error);
}];
}
#pragma mark - POST请求自动缓存
+ (XDURLSessionTask *)POST:(NSString *)URL parameters:(NSDictionary *)parameters responseCache:(HttpRequestCache)responseCache progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//读取缓存
responseCache?responseCache([XDNetWorkingCacheManager getResponseCacheForKey:URL]):nil;
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager POST:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
progress ? progress(uploadProgress) : nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success?success(responseObject): nil;
//对数据进行异步缓存
[XDNetWorkingCacheManager saveResponseCache:responseObject forKey:URL];
XDLog(@"responseObject = %@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
failure ? failure(error) : nil;
XDLog(@"error = %@",error);
}];
}
#pragma mark - 网络请求的类方法 --- get / post / put / delete
/*!
* 网络请求的实例方法
*
* @param type get / post / put / delete
* @param urlString 请求的地址
* @param parameters 请求的参数
* @param successBlock 请求成功的回调
* @param failureBlock 请求失败的回调
* @param progress 进度
*/
+ (XDURLSessionTask *)ba_requestWithType:(XDHttpRequestType)type UrlString:(NSString *)urlString Parameters:(NSDictionary *)parameters progress:(HttpProgress)progress SuccessBlock:(HttpRequestSuccess)successBlock FailureBlock:(HttpRequestFailed)failureBlock
{
if (urlString == nil)
{
return nil;
}
XDWeak;
/*! 检查地址中是否有中文 */
NSString *URLString = [NSURL URLWithString:urlString] ? urlString : [self strUTF8Encoding:urlString];
NSString *requestType;
switch (type) {
case 0:
requestType = @"Get";
break;
case 1:
requestType = @"Post";
break;
case 2:
requestType = @"Put";
break;
case 3:
requestType = @"Delete";
break;
default:
break;
}
NSLog(@"******************** 请求参数 ***************************");
NSLog(@"请求头: %@\n请求方式: %@\n请求URL: %@\n请求param: %@\n\n",[self createAFHTTPSessionManager].requestSerializer.HTTPRequestHeaders, requestType, URLString, parameters);
NSLog(@"********************************************************");
XDURLSessionTask *sessionTask = nil;
if (type == XDHttpRequestTypeGet)
{
sessionTask = [[self createAFHTTPSessionManager] GET:URLString parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
progress?progress(downloadProgress):nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
/****************************************************/
// 如果请求成功 , 回调请求到的数据 , 同时 在这里 做本地缓存
NSString *path = [NSString stringWithFormat:@"%ld.plist", [URLString hash]];
// 存储的沙盒路径
NSString *path_doc = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"如果请求成功 , 回调请求到的数据 , 同时 在这里 做本地缓存,存储的沙盒路径:%@",path_doc);
// 归档
[NSKeyedArchiver archiveRootObject:responseObject toFile:[path_doc stringByAppendingPathComponent:path]];
successBlock?successBlock(responseObject):nil;
[[weakSelf tasks] removeObject:sessionTask];
//[self writeInfoWithDict:(NSDictionary *)responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failureBlock?failureBlock(error):nil;
NSLog(@"错误信息:%@",error);
[[weakSelf tasks] removeObject:sessionTask];
}];
}
else if (type == XDHttpRequestTypePost)
{
sessionTask = [[self createAFHTTPSessionManager] POST:URLString parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
progress?progress(uploadProgress):nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
/* ************************************************** */
// 如果请求成功 , 回调请求到的数据 , 同时 在这里 做本地缓存
NSString *path = [NSString stringWithFormat:@"%ld.plist", [URLString hash]];
// 存储的沙盒路径
NSString *path_doc = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSLog(@"如果请求成功 , 回调请求到的数据 , 同时 在这里 做本地缓存,存储的沙盒路径:%@",path_doc);
// 归档
[NSKeyedArchiver archiveRootObject:responseObject toFile:[path_doc stringByAppendingPathComponent:path]];
successBlock?successBlock(responseObject):nil;
[[weakSelf tasks] removeObject:sessionTask];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failureBlock?failureBlock(error):nil;
NSLog(@"错误信息:%@",error);
[[weakSelf tasks] removeObject:sessionTask];
}];
}
else if (type == XDHttpRequestTypePut)
{
sessionTask = [[self createAFHTTPSessionManager] PUT:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (successBlock)
{
successBlock(responseObject);
}
[[weakSelf tasks] removeObject:sessionTask];
//[self writeInfoWithDict:(NSDictionary *)responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failureBlock)
{
failureBlock(error);
}
[[weakSelf tasks] removeObject:sessionTask];
}];
}
else if (type == XDHttpRequestTypeDelete)
{
sessionTask = [[self createAFHTTPSessionManager] DELETE:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (successBlock)
{
successBlock(responseObject);
}
[[weakSelf tasks] removeObject:sessionTask];
// [self writeInfoWithDict:(NSDictionary *)responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failureBlock)
{
failureBlock(error);
}
[[weakSelf tasks] removeObject:sessionTask];
}];
}
if (sessionTask)
{
[[weakSelf tasks] addObject:sessionTask];
}
return sessionTask;
}
#pragma mark - 上传图片文件
+ (XDURLSessionTask *)uploadWithURL:(NSString *)URL parameters:(NSDictionary *)parameters images:(NSArray *)images name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType progress:(HttpProgress)progress success:(HttpRequestSuccess)success failure:(HttpRequestFailed)failure
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager POST:URL parameters:parameters constructingBodyWithBlock:^(id _Nonnull formData) {
//压缩-添加-上传图片
[images enumerateObjectsUsingBlock:^(UIImage * _Nonnull image, NSUInteger idx, BOOL * _Nonnull stop) {
NSData *imageData = [NSData data];
if (UIImagePNGRepresentation(image) == nil) {
imageData = UIImageJPEGRepresentation(image, 1);
} else {
imageData = UIImagePNGRepresentation(image);
}
[formData appendPartWithFileData:imageData name:name fileName:[NSString stringWithFormat:@"%@%ld.%@",fileName,idx,mimeType?mimeType:@"jpeg"] mimeType:[NSString stringWithFormat:@"image/%@",mimeType?mimeType:@"jpeg"]];
}];
} progress:^(NSProgress * _Nonnull uploadProgress) {
//上传进度
progress ? progress(uploadProgress) : nil;
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success?success(responseObject): nil;
XDLog(@"responseObject = %@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
failure ? failure(error) : nil;
XDLog(@"error = %@",error);
}];
}
#pragma mark - 下载文件
+ (XDURLSessionTask *)downloadWithURL:(NSString *)URL fileDir:(NSString *)fileDir progress:(HttpProgress)progress success:(void(^)(NSString *))success failure:(HttpRequestFailed)failure
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:URL]];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
//下载进度
progress ? progress(downloadProgress) : nil;
XDLog(@"下载进度:%.2f%%",100.0*downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
//拼接缓存目录
NSString *downloadDir = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:fileDir ? fileDir : @"Download"];
//打开文件管理器
NSFileManager *fileManager = [NSFileManager defaultManager];
//创建Download目录
[fileManager createDirectoryAtPath:downloadDir withIntermediateDirectories:YES attributes:nil error:nil];
//拼接文件路径
NSString *filePath = [downloadDir stringByAppendingPathComponent:response.suggestedFilename];
XDLog(@"下载文件所在文件夹downloadDir = %@",downloadDir);
//返回文件位置的URL路径
return [NSURL fileURLWithPath:filePath];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
success ? success(filePath.absoluteString /** NSURL->NSString*/) : nil;
failure && error ? failure(error) : nil;
}];
//开始下载
[downloadTask resume];
return downloadTask;
}
#pragma mark -- POST/GET网络请求 --
+ (XDURLSessionTask *)requestWithURLString:(NSString *)URLString
parameters:(id)parameters
requestMethod:(RequestMethod)method
success:(void (^)(id))success
failure:(void (^)(NSError *))failure {
switch (method) {
case GET:
{
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}
break;
case POST:
{
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}
case PUT:
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:
URLString]];
request.HTTPMethod = @"PUT";
// [request setValue:[@"admin:adminpasswd" q_basic64AuthEncode] forHTTPHeaderField:@"Authorization"];
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"HQ_0005.jpg" withExtension:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc]
initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURLSessionUploadTask * UploadTask = [manager uploadTaskWithRequest:request fromFile:fileURL progress:^(NSProgress * _Nonnull uploadProgress) {
// float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
// dispatch_async(dispatch_get_main_queue(), ^{
// [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
// });
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error == nil && responseObject != nil) {
NSLog(@"success: %@ --- %@", responseObject, [responseObject class]);
} else {
NSLog(@"failure: %@", error);
}
}];
[UploadTask resume];
return UploadTask;
}
case PATCH:
{
return nil;
}
case DELETE:
{
return nil;
}
case HEAD:
{
AFHTTPSessionManager *manager = [self createAFHTTPSessionManager];
return [manager HEAD:URLString parameters:nil success:^(NSURLSessionDataTask * _Nonnull task) {
NSLog(@"success: %@ --- %lld", task.response.suggestedFilename, task.response.expectedContentLength);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"failure: %@", error);
}];
}
break;
}
}
#pragma mark - url 中文格式化
+ (NSString *)strUTF8Encoding:(NSString *)str
{
/*! ios9适配的话 打开第一个 */
if ([[UIDevice currentDevice] systemVersion].floatValue >= 9.0)
{
return [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];
}
else
{
return [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
}
+ (NSMutableArray *)tasks
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"创建任务数组");
tasks = [[NSMutableArray alloc] init];
});
return tasks;
}
@end
//
// XDDownLoadData.h
// XDAFHTTPSessionManager
//
// Created by 窦心东 on 2016/12/2.
// Copyright © 2016年 窦心东. All rights reserved.
//
#import
@interface XDDownLoadData : NSObject
singleton_interface(XDDownLoadData)
@property (nonatomic, strong) AFURLSessionManager *manager;
@property (nonatomic, retain) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, strong) NSData *resumeData;
@property (nonatomic, strong) NSString *resumeTmpPath;
@property (nonatomic, assign) BOOL isDownloading;
@property (nonatomic, assign) BOOL isPause;
- (NSString *)resumeTmpPath;
// 开始下载
- (void)start;
// 继续下载
- (void)goon;
// 暂停下载
- (void)pause;
// 停止下载
- (void)stop;
- (void)downloadProgress:(NSProgress *)downloadProgress;
- (void)downloadCompletion:(NSURL *)filePath error:(NSError *)error;
@end
//
// XDDownLoadData.m
// XDAFHTTPSessionManager
//
// Created by 窦心东 on 2016/12/2.
// Copyright © 2016年 窦心东. All rights reserved.
//
#import "XDDownLoadData.h"
@implementation XDDownLoadData
singleton_implementation(XDDownLoadData)
- (AFURLSessionManager *)manager {
if (_manager == nil) {
_manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
_manager.responseSerializer = [AFHTTPResponseSerializer serializer];
}
return _manager;
}
- (NSString *)resumeTmpPath {
if (_resumeTmpPath == nil) {
_resumeTmpPath = [@"resumeTmpData.tmp" q_appendCachePath];
}
return _resumeTmpPath;
}
// 开始下载
- (void)start {
if (self.isDownloading) {
NSLog(@"已经开始下载");
return;
}
if (self.isPause) {
NSLog(@"继续下载");
[self.downloadTask resume];
self.isPause = NO;
self.isDownloading = YES;
return;
}
//如果内存中 这个路径的文件不在或者没有大小, 就进行开始 ; 反之有的话,继续下载
if (![[NSFileManager defaultManager] fileExistsAtPath:self.resumeTmpPath]) {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]];
self.downloadTask = [self.manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
[self downloadProgress:downloadProgress];
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
[self downloadCompletion:filePath error:error];
}];
[self.downloadTask resume];
self.isPause = NO;
self.isDownloading = YES;
} else {
[self goon];
}
}
// 继续下载
- (void)goon {
if (self.isDownloading) {
NSLog(@"已经开始下载");
return;
}
if (self.isPause) {
[self.downloadTask resume];
NSLog(@"继续下载");
} else {
self.resumeData = [NSData dataWithContentsOfFile:self.resumeTmpPath];
self.downloadTask = [self.manager downloadTaskWithResumeData:self.resumeData progress:^(NSProgress * _Nonnull downloadProgress) {
[self downloadProgress:downloadProgress];
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
[self downloadCompletion:filePath error:error];
}];
[self.downloadTask resume];
NSLog(@"继续下载");
}
self.isPause = NO;
self.isDownloading = YES;
}
// 暂停下载
- (void)pause {
if (!self.isDownloading) {
NSLog(@"已经停止下载");
return;
}
[self.downloadTask suspend];
NSLog(@"暂停下载");
self.isPause = YES;
self.isDownloading = NO;
}
// 停止下载
- (void)stop {
if (!self.isDownloading) {
NSLog(@"已经停止下载");
return;
}
[self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
if (resumeData) {
self.resumeData = resumeData;
[self.resumeData writeToFile:self.resumeTmpPath atomically:YES];
}
self.downloadTask = nil;
NSLog(@"停止下载");
}];
self.isDownloading = NO;
}
- (void)downloadProgress:(NSProgress *)downloadProgress {
float progress = (1.0 *downloadProgress.completedUnitCount / downloadProgress.totalUnitCount)*100;
dispatch_async(dispatch_get_main_queue(), ^{
// [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]];
NSLog(@"进度%.0f%%",progress);
});
}
- (void)downloadCompletion:(NSURL *)filePath error:(NSError *)error {
self.isDownloading = NO;
if (error == nil) {
NSLog(@"success: %@", filePath.path);
[[NSFileManager defaultManager] removeItemAtPath:self.resumeTmpPath error:nil];
} else {
NSLog(@"%@", error);
if (error) {
NSLog(@"failure: %@", error.userInfo[NSLocalizedDescriptionKey]);
self.resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
}
if ([error.localizedFailureReason isEqualToString:@"No such file or directory"]) {
[[NSFileManager defaultManager] removeItemAtPath:self.resumeTmpPath error:nil];
[self start];
}
}
}
@end
//
// ViewController.m
// XDAFHTTPSessionManager
//
// Created by 窦心东 on 2016/12/2.
// Copyright © 2016年 窦心东. All rights reserved.
//
#import "ViewController.h"
#import "XDDownLoadData.h"
#import "XDHTTPSessionManager.h"
#define XDSessionManager [XDHTTPSessionManager shareManager]
#define DownLoadData [XDDownLoadData sharedXDDownLoadData]
@interface ViewController (){
UIButton *button;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// button = [UIButton buttonWithType:UIButtonTypeCustom];
// [button setTitle:@"开始" forState:UIControlStateNormal];
// [button setBackgroundColor:[UIColor redColor]];
// button.frame = CGRectMake(100, 100, 100, 100);
// [self.view addSubview:button];
// [button addTarget:self action:@selector(buttonclick) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonclick{
//封装好了,展示需要自己写,这仅仅是显示一下更高深的 需要自行使用API
if ([button.titleLabel.text isEqualToString:@"开始"]) {
[button setTitle:@"暂停" forState:UIControlStateNormal];
[DownLoadData start];
} else {
[button setTitle:@"开始" forState:UIControlStateNormal];
[DownLoadData pause];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//当前只示例两个 其他方式一样的形式
//进行数据下载
[self download];
//进行post请求
[self postData];
}
- (void)download{
[XDHTTPSessionManager downloadWithURL:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4" fileDir:@"video" progress:^(NSProgress *progress) {
[DownLoadData downloadProgress:progress];
} success:^(NSString *filePath) {
NSLog(@"全路径是filePath.absoluteString ======%@",filePath);
} failure:^(NSError *error) {
NSLog(@"error == %@",error);
}];
}
- (void)postData{
NSDictionary *parameters = @{
@"pageNo":@1,
@"pageSize":@"20"
};
[XDHTTPSessionManager POST:@"http://115.28.11.62:8080/heal/api/heal/plan/list" parameters:parameters progress:^(NSProgress *progress) {
[DownLoadData downloadProgress:progress];
} success:^(id responseObject) {
NSLog(@"responseObject%@",[responseObject yy_modelDescription]);
} failure:^(NSError *error) {
NSLog(@"error==%@",error);
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
项目地址:https://github.com/douxindong/XDAFHTTPSessionManager.git