在开发过程中,经常性的要把图片资源发送给服务器, AFNetworking 基本是网络处理的基本框架,在最新 AFN 3.0.0 以后, AFN 已经摒弃了对 NSURLConnection 的支持,全力使用 NSURLSession 来处理网络请求.但一些老一点的项目当中, AFN 可能还比较古老,老框架和最新的 AFN 3.1.0 在网络请求上面有什么区别呢? 就以图片上传为例:
(1) AFN2.0 以前的来上传图片:
1. 设置请求头
+ (AFHTTPClient *)getNsurlRequestPath:(NSString *)path params:(NSDictionary *)params method:(NSString *)method
{
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:shareTool.baseUrl]];
//设置header
[client setDefaultHeader:@"xxx" value:xxx];
[client setDefaultHeader:@"xxx" value:xxx];
// 或取当前时间戳
NSString *timeInterval = [NSString stringWithFormat:@"%f",[[NSDate date] timeIntervalSince1970]];
[client setDefaultHeader:@"r" value:timeInterval];
// EncryPtionTool MD5 加密处理类
[client setAuthorizationHeaderWithUsername:kAppName password:[EncryPtionTool GetMd5String:[NSString stringWithFormat:@"xxx%@%@",timeInterval,kKey]]];
return client;
}
+(void)upLoadImageSuccess:(void (^)())success failure:(void (^)(NSError *))failure
{
NSString* path=@"xxxxxxxxxxxxx";
NSMutableDictionary* param=[NSMutableDictionary dictionary];
param[@"xxx"]=@"";
AFHTTPClient* client=[self getNsurlRequestPath:path params:param method:@"post"];
// 上传图片
NSURLRequest* request= [client multipartFormRequestWithMethod:@"post" path:path parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// 要上传的图片 以单张图片为例
UIImage *image = [UIImage imageNamed:@"image_test"];
NSData *data = UIImageJPEGRepresentation(image, 0.7);
while (data.length > 1024 * 500) { // 压缩小于 500 k
image = [[UIImage alloc] initWithData:data];
data = UIImageJPEGRepresentation(image, 0.07);
}
// 在网络开发中,上传文件时,是文件不允许被覆盖,文件重名
// 要解决此问题,
// 可以在上传时使用当前的系统事件作为文件名
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 设置时间格式
formatter.dateFormat = @"yyyyMMddHHmmss";
NSString *str = [formatter stringFromDate:[NSDate date]];
NSString *fileName = [NSString stringWithFormat:@"%@.png", str];
[formData appendPartWithFileData:data name:@"file" fileName:fileName mimeType:@"image/png"];
}];
AFHTTPRequestOperation* operation=[[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:operation.responseData options:NSJSONReadingMutableContainers error:nil];
if ([JSON[@"code"] integerValue] != 0) {
NSError* error=[[NSError alloc] initWithDomain:JSON[@"msg"] code:[JSON[@"code"] integerValue] userInfo:@{@"msg" : JSON[@"msg"]}];
if (failure) {
failure(error);
return ;
}
}
if (success) {
success();
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) {
failure(error);
}
}];
/**
@param bytesWritten 每次写进的字节数
@param totalBytesWritten 总共写进的字节数
@param totalBytesExpectedToWrite 期望写进的字节数
*/
__block NSString* total=nil;
__block NSString* totalExpect=nil;
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
total=[NSString stringWithFormat:@"%lld",totalBytesWritten ];
totalExpect=[NSString stringWithFormat:@"%lld",totalBytesExpectedToWrite ];
// 监听上传进度
CGFloat progress =[total floatValue] / [totalExpect floatValue] ;
NSLog(@"---%f",progress);
NSLog(@"Sent %d 总共 %lld of %lld bytes",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
}];
// 执行操作
[client.operationQueue addOperation:operation];
}
(2) AFN 3.1.0 上传图片
1.设置请求头
+(AFHTTPSessionManager*) sessionManager
{
AFHTTPSessionManager* sessinManager=[[AFHTTPSessionManager alloc] initWithBaseURL:[NSURLURLWithString:kBaseURL]];
sessinManager.responseSerializer=[AFJSONResponseSerializer serializer];
// 设置请求头
[sessinManager.requestSerializer setValue:xxx forHTTPHeaderField:@"xxx"];
[sessinManager.requestSerializer setValue:xxx forHTTPHeaderField:@"xxxx"];
// 时间戳
NSString *timeInterval = [NSString stringWithFormat:@"%f",[[NSDate date] timeIntervalSince1970]];
[sessinManager.requestSerializer setValue:timeInterval forHTTPHeaderField:@"r"];
NSString* passWord= [EncryPtionTool GetMd5String:[NSStringstringWithFormat:@"xxx%@%@",timeInterval,kKey]];
[sessinManager.requestSerializer setAuthorizationHeaderFieldWithUsername:kAppName password:passWord];
sessinManager.requestSerializer.timeoutInterval=5.0;
return sessinManager;
}
2.发送请求
+(void)downUpImageSuccess:(void (^)(NSDictionary *))success failure:(void (^)(NSError *))failure
{
AFHTTPSessionManager* sessionManager= [self sessionManager];
NSString* path=@"xxxxxx";
NSMutableDictionary* param=[NSMutableDictionary dictionary];
param[@"xxxx"]=@"";
[sessionManager POST:path parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
/***** 在这里直接添加上传的图片 *****/
UIImage *image = [UIImage imageNamed:@"image_test"];
NSData *data = UIImagePNGRepresentation(image);
// 在网络开发中,上传文件时,是文件不允许被覆盖,文件重名
// 要解决此问题,
// 可以在上传时使用当前的系统事件作为文件名
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// 设置时间格式
formatter.dateFormat = @"yyyyMMddHHmmss";
NSString *str = [formatter stringFromDate:[NSDate date]];
NSString *fileName = [NSString stringWithFormat:@"%@.png", str];
[formData appendPartWithFileData:data name:@"file" fileName:fileName mimeType:@"image/png"];
} progress:^(NSProgress * _Nonnull uploadProgress) {
// 获取上传进度
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable JSON) {
if ([JSON[@"code"] integerValue] != 0) { // 返回 code 值不为 0
NSError* error=[[NSError alloc] initWithDomain:JSON[@"msg"] code:[JSON[@"code"] integerValue] userInfo:@{@"msg" : JSON[@"msg"]}];
failure(error);
return ;
}
NSLog(@"上传成功");
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"上传失败");
failure(error);
}];
}
由上面可以看到, AFN 3.1.0 对 NSURLSession 封装,除了性能更优,相对以前,代码更集中,更易处理.