iOS开发AFN使用二:AFN文件下载与文件上传
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS开发AFN使用二:AFN文件下载与文件上传相关的知识,希望对你有一定的参考价值。
#import "ViewController.h" #import "AFNetworking.h" @interface ViewController () @end @implementation ViewController -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self download]; } -(void)download { //1.创建会话管理者 AFHTTPSessionManager *manager =[AFHTTPSessionManager manager]; NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; //2.下载文件 /* 第一个参数:请求对象 第二个参数:progress 进度回调 downloadProgress 第三个参数:destination 回调(目标位置) 有返回值 targetPath:临时文件路径 response:响应头信息 第四个参数:completionHandler 下载完成之后的回调 filePath:最终的文件路径 */ /* 第一个参数:请求对象 第二个参数:进度回调 downloadProgress.completedUnitCount :已经下载的数据 downloadProgress.totalUnitCount:数据的总大小 第三个参数:destination回调,该block需要返回值(NSURL类型),告诉系统应该把文件剪切到什么地方 targetPath:文件的临时保存路径tmp,随时可能被删除 response:响应头信息 第四个参数:completionHandler请求完成后回调 response:响应头信息 filePath:文件的保存路径,即destination回调的返回值 error:错误信息 */ NSURLSessionDownloadTask *download = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { //监听下载进度 //completedUnitCount 已经下载的数据大小 //totalUnitCount 文件数据的中大小 NSLog(@"%f",1.0 *downloadProgress.completedUnitCount / downloadProgress.totalUnitCount); } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { /** * 1:1:请求路径:NSUrl *url = [NSUrl urlWithString:path];从网络请求路径 2:把本地的file文件路径转成url,NSUrl *url = [NSURL fileURLWithPath:fullPath]; 2:返回值是一个下载文件的路径 * */ NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename]; NSLog(@"targetPath:%@",targetPath); NSLog(@"fullPath:%@",fullPath); return [NSURL fileURLWithPath:fullPath]; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { /** *filePath:下载后文件的保存路径 */ NSLog(@"%@",filePath); }]; //3.执行Task [download resume]; } @end
(2)使用AFN下载文件
```objc
-(void)download
{
//1.创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_13.png"]];
//3.创建下载Task
/*
第一个参数:请求对象
第二个参数:进度回调
downloadProgress.completedUnitCount :已经下载的数据
downloadProgress.totalUnitCount:数据的总大小
第三个参数:destination回调,该block需要返回值(NSURL类型),告诉系统应该把文件剪切到什么地方
targetPath:文件的临时保存路径
response:响应头信息
第四个参数:completionHandler请求完成后回调
response:响应头信息
filePath:文件的保存路径,即destination回调的返回值
error:错误信息
*/
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(@"%f",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
NSLog(@"%@\n%@",targetPath,fullPath);
return [NSURL fileURLWithPath:fullPath];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
NSLog(@"%@",filePath);
}];
//4.执行Task
[downloadTask resume];
}
```
二:文件上传
#import "ViewController.h" #import "AFNetworking.h" #define Kboundary @"----WebKitFormBoundaryjv0UfA04ED44AhWx" #define KNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding] @interface ViewController () @end @implementation ViewController -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self upload2]; } //不推荐 -(void)upload { //1.创建会话管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //2.1url NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"]; //2.2创建请求对象 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //2.3 设置请求方法 request.HTTPMethod = @"POST"; //2.4 设请求头信息 [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary] forHTTPHeaderField:@"Content-Type"]; //3.发送请求上传文件 NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromData:[self getBodyData] progress:^(NSProgress * _Nonnull uploadProgress) { NSLog(@"%f",1.0 * uploadProgress.completedUnitCount/ uploadProgress.totalUnitCount); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { NSLog(@"%@",responseObject); }]; //4.执行task [uploadTask resume]; } -(void)upload2 { //1.创建会话管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // NSDictionary *dictM = @{} //2.发送post请求上传文件 /* 第一个参数:请求路径 第二个参数:字典(非文件参数) 第三个参数:constructingBodyWithBlock 处理要上传的文件数据 第四个参数:进度回调 第五个参数:成功回调 responseObject:响应体信息 第六个参数:失败回调 */ [manager POST:@"http://120.25.226.186:32812/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { /** * 1:将image转换成NSData:可用 UIImagePNGRepresentation,也可用UIImageJPEGRepresentation 2:data转换成image:UIImage *image = [UIImage imageWithData:data]; 3:url:1;网络路径:NSUrl urlWithString 2:NSUrl fileUrlWithStr:本地文件路径 4:第三种方法:没有传fileName 和 mimeType,由AFN内部去自动设置,fileName截取的文件的url路径,mimeType由c语言内部去获取 */ UIImage *image = [UIImage imageNamed:@"Snip20160227_128"]; NSData *imageData = UIImagePNGRepresentation(image); //使用formData来拼接数据 /* 第一个参数:二进制数据 要上传的文件参数 第二个参数:服务器规定的 第三个参数:该文件上传到服务器以什么名称保存 */ //[formData appendPartWithFileData:imageData name:@"file" fileName:@"xxxx.png" mimeType:@"image/png"]; //[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"/Users/xiaomage/Desktop/Snip20160227_128.png"] name:@"file" fileName:@"123.png" mimeType:@"image/png" error:nil]; [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"/Users/xiaomage/Desktop/Snip20160227_128.png"] name:@"file" error:nil]; } progress:^(NSProgress * _Nonnull uploadProgress) { NSLog(@"%f",1.0 * uploadProgress.completedUnitCount/uploadProgress.totalUnitCount); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"上传成功---%@",responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"上传失败---%@",error); }]; } -(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:@"Snip20160227_128"]; //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; } @end
###2.AFN文件上传
```objc
1.文件上传拼接数据的第一种方式
[formData appendPartWithFileData:data name:@"file" fileName:@"xxoo.png" mimeType:@"application/octet-stream"];
2.文件上传拼接数据的第二种方式
[formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];
3.文件上传拼接数据的第三种方式
[formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
4.【注】在资料中已经提供了一个用于文件上传的分类。
/*文件上传相关的代码如下*/
-(void)upload1
{
//1.创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.处理参数(非文件参数)
NSDictionary *dict = @{
@"username":@"123"
};
//3.发送请求上传文件
/*
第一个参数:请求路径(NSString类型)
第二个参数:非文件参数,以字典的方式传递
第三个参数:constructingBodyWithBlock 在该回调中拼接文件参数
第四个参数:progress 进度回调
uploadProgress.completedUnitCount:已经上传的数据大小
uploadProgress.totalUnitCount:数据的总大小
第五个参数:success 请求成功的回调
task:上传Task
responseObject:服务器返回的响应体信息(已经以JSON的方式转换为OC对象)
第六个参数:failure 请求失败的回调
task:上传Task
error:错误信息
*/
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
UIImage *image = [UIImage imageNamed:@"Snip20160117_1"];
NSData *imageData = UIImagePNGRepresentation(image);
//在该block中拼接要上传的文件参数
/*
第一个参数:要上传的文件二进制数据
第二个参数:文件参数对应的参数名称,此处为file是该台服务器规定的(通常会在接口文档中提供)
第三个参数:该文件上传到服务后以什么名称保存
第四个参数:该文件的MIMeType类型
*/
[formData appendPartWithFileData:imageData name:@"file" fileName:@"123.png" mimeType:@"image/png"];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"请求成功----%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"请求失败----%@",error);
}];
}
-(void)upload2
{
//1.创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.处理参数(非文件参数)
NSDictionary *dict = @{
@"username":@"123"
};
//3.发送请求上传文件
/*
第一个参数:请求路径(NSString类型)
第二个参数:非文件参数,以字典的方式传递
第三个参数:constructingBodyWithBlock 在该回调中拼接文件参数
第四个参数:progress 进度回调
uploadProgress.completedUnitCount:已经上传的数据大小
uploadProgress.totalUnitCount:数据的总大小
第五个参数:success 请求成功的回调
task:上传Task
responseObject:服务器返回的响应体信息(已经以JSON的方式转换为OC对象)
第六个参数:failure 请求失败的回调
task:上传Task
error:错误信息
*/
[manager POST:@"http://120.25.226.186:32812/upload" parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
NSURL *fileUrl = [NSURL fileURLWithPath:@"/Users/文顶顶/Desktop/Snip20160117_1.png"];
//在该block中拼接要上传的文件参数
//第一种拼接方法
/*
第一个参数:要上传的文件的URL路径
第二个参数:文件参数对应的参数名称,此处为file是该台服务器规定的(通常会在接口文档中提供)
第三个参数:该文件上传到服务后以什么名称保存
第四个参数:该文件的MIMeType类型
第五个参数:错误信息,传地址
*/
//[formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"1234.png" mimeType:@"image/png" error:nil];
//第二种拼接方法:简写方法
/*
第一个参数:要上传的文件的URL路径
第二个参数:文件参数对应的参数名称,此处为file
第三个参数:错误信息
说明:AFN内部自动获得路径URL地址的最后一个节点作为文件的名称,内部调用C语言的API获得文件的类型
*/
[formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"请求成功----%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"请求失败----%@",error);
}];
}
```
以上是关于iOS开发AFN使用二:AFN文件下载与文件上传的主要内容,如果未能解决你的问题,请参考以下文章
ios开发之--使用AFN上传3.1.0上传视频,不走成功回调原因及解决方法