iOS之文件上传、下载(上传)

iOS中用系统提供的API能实现能实现文件的上传与下载,分别有两种方式。NSURLConnectionNSURLSession

其中NSURLConnection是使用很久的的一种方式,NSURLSession是新出来的一种方式。


一、 POST方式上传

POST方式提交信息默认使用的是 :
* Content-Type :   application/x-www-form-urlencoded .
* 输入中文时 , post 方式自动进行转义 ( 苹果中自动 ).

国内的绝大多数网站都采用这种方式 上传文件 ( 支持二进制文件 )
* Content-Type : multipart/form-data ( 上传文件 )
* 都会限制上传文件的大小 一般是 2M 或者更小。


在苹果中进行上传操作十分麻烦。需要拼接好上传所需要的字符串格式,然后才能实现上传。(还要加上头部)

iOS之文件上传、下载(上传)_第1张图片

其他平台做的好一点的可能封装好了,不需要自己拼接字符串格式。因此iOS中很少用这种方式上传

示例代码:

[objc] view plain copy
  1. #import "skyUploadFile.h"  
  2.   
  3. #define kTimeOut 5.0f  
  4.   
  5. @implementation skyUploadFile  
  6. /** 分隔字符串 */  
  7. static NSString *boundaryStr = @"--";  
  8. /** 本次上传标示字符串 */  
  9. static NSString *randomIDStr;  
  10. /** 上传(php)脚本中,接收文件字段 */  
  11. static NSString *uploadID;  
  12.   
  13. - (instancetype)init  
  14. {  
  15.     self = [super init];  
  16.     if (self) {  
  17.         /** 本次上传标示字符串 */  
  18.         randomIDStr = @"itcastupload";  
  19.         /** 上传(php)脚本中,接收文件字段 */  
  20.         // 可以咨询公司的网站开发程序员  
  21.         // 或者用FireBug自己跟踪调试  
  22.         uploadID = @"uploadFile";  
  23.     }  
  24.     return self;  
  25. }  
  26.   
  27. #pragma mark - 成员方法.  用NSURLSession来完成上传  
  28. - (void)uploadFile:(NSString *)path fileName:(NSString *)fileName completion:(void (^)(NSString *string))completion  
  29. {  
  30.     // 1. url 提示:真正负责文件上传的是php文件,而不是html文件  
  31.     NSURL *url = [NSURL URLWithString:@"http://localhost/new/post/upload.php"];  
  32.       
  33.     // 2. request  
  34.     NSURLRequest *request = [self requestForUploadURL:url uploadFileName:fileName localFilePath:path];  
  35.       
  36.     // 3. session(回话)  
  37.     // 全局网络回话,为了方便程序员使用网络服务  
  38.     NSURLSession *session = [NSURLSession sharedSession];  
  39.       
  40.     // 4. 数据任务-> 任务都是由回话发起的  
  41.     /** URLSession的任务,默认都是在其他线程工作的,默认都是异步的 */  
  42.     [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {  
  43.           
  44.         id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];  
  45.           
  46.         NSLog(@"%@ %@", result, [NSThread currentThread]);  
  47.           
  48.         dispatch_async(dispatch_get_main_queue(), ^{  
  49.             if (completion) {  
  50.                 completion(@"下载完成");  
  51.             }  
  52.         });  
  53.     }] resume];  
  54.       
  55.     //    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {  
  56.     //  
  57.     //        id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];  
  58.     //  
  59.     //        NSLog(@"%@ %@", result, [NSThread currentThread]);  
  60.     //  
  61.     //        dispatch_async(dispatch_get_main_queue(), ^{  
  62.     //            if (completion) {  
  63.     //                completion(@"下载完成");  
  64.     //            }  
  65.     //        });  
  66.     //    }];  
  67.     //      
  68.     //    // 5. 启动任务  
  69.     //    [task resume];  
  70. }  
  71.   
  72. #pragma mark - 私有方法 : 拼字符串  
  73. /** 拼接顶部字符串 */  
  74. - (NSString *)topStringWithMimeType:(NSString *)mimeType uploadFile:(NSString *)uploadFile  
  75. {  
  76.     NSMutableString *strM = [NSMutableString string];  
  77.       
  78.     [strM appendFormat:@"%@%@\n", boundaryStr, randomIDStr];  
  79.     [strM appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\n", uploadID, uploadFile];  
  80.     [strM appendFormat:@"Content-Type: %@\n\n", mimeType];  
  81.       
  82.     NSLog(@"顶部字符串:%@", strM);  
  83.     return [strM copy];  
  84. }  
  85.   
  86. /** 拼接底部字符串 */  
  87. - (NSString *)bottomString  
  88. {  
  89.     NSMutableString *strM = [NSMutableString string];  
  90.       
  91.     [strM appendFormat:@"%@%@\n", boundaryStr, randomIDStr];  
  92.     [strM appendString:@"Content-Disposition: form-data; name=\"submit\"\n\n"];  
  93.     [strM appendString:@"Submit\n"];  
  94.     [strM appendFormat:@"%@%@--\n", boundaryStr, randomIDStr];  
  95.       
  96.     NSLog(@"底部字符串:%@", strM);  
  97.     return [strM copy];  
  98. }  
  99.   
  100. /** 指定全路径文件的mimeType */  
  101. - (NSString *)mimeTypeWithFilePath:(NSString *)filePath  
  102. {  
  103.     // 1. 判断文件是否存在  
  104.     if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {  
  105.         return nil;  
  106.     }  
  107.       
  108.     // 2. 使用HTTP HEAD方法获取上传文件信息  
  109.     NSURL *url = [NSURL fileURLWithPath:filePath];  
  110.     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];  
  111.       
  112.     // 3. 调用同步方法获取文件的MimeType  
  113.     NSURLResponse *response = nil;  
  114.     [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];  
  115.       
  116.     return response.MIMEType;  
  117. }  
  118.   
  119. /** 上传文件网络请求 */  
  120. - (NSURLRequest *)requestForUploadURL:(NSURL *)url uploadFileName:(NSString *)fileName localFilePath:(NSString *)filePath  
  121. {  
  122.     // 0. 获取上传文件的mimeType  
  123.     NSString *mimeType = [self mimeTypeWithFilePath:filePath];  
  124.     if (!mimeType) return nil;  
  125.       
  126.     // 1. 拼接要上传的数据体  
  127.     NSMutableData *dataM = [NSMutableData data];  
  128.     [dataM appendData:[[self topStringWithMimeType:mimeType uploadFile:fileName] dataUsingEncoding:NSUTF8StringEncoding]];  
  129.     // 拼接上传文件本身的二进制数据  
  130.     [dataM appendData:[NSData dataWithContentsOfFile:filePath]];  
  131.     [dataM appendData:[[self bottomString] dataUsingEncoding:NSUTF8StringEncoding]];  
  132.       
  133.     // 2. 设置请求  
  134.     NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeOut];  
  135.     // 1> 设定HTTP请求方式  
  136.     requestM.HTTPMethod = @"POST";  
  137.     // 2> 设置数据体  
  138.     requestM.HTTPBody = dataM;  
  139.     // 3> 指定Content-Type  
  140.     NSString *typeStr = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", randomIDStr];  
  141.     [requestM setValue:typeStr forHTTPHeaderField:@"Content-Type"];  
  142.     // 4> 指定数据长度  
  143.     NSString *lengthStr = [NSString stringWithFormat:@"%@", @([dataM length])];  
  144.     [requestM setValue:lengthStr forHTTPHeaderField:@"Content-Length"];  
  145.       
  146.     return [requestM copy];  
  147. }  
注意: POST 上传时 , 不允许重名 . ( 否则出错 )


二、 PUT方式上传

session 中的 upload 方法只能用于 PUT 上传 , 不能用于 POST 上传 .

PUT 方式上传的 好处 : ( 需要身份验证 )
* 不用像 POST 一样 , 拼一堆字符串 .
* 直接 base64 编码一下身份验证 session upload 一调用就行了 .
* 没有文件大小限制 .
* 即时通讯 里面用的多 . ( 发图片 / 发语音 )
[objc] view plain copy
  1. - (void)putFile  
  2. {  
  3.     // 1. url 最后一个是要上传的文件名  
  4.     NSURL *url = [NSURL URLWithString:@"http://localhost/uploads/abcd"]; //abcd为文件名  
  5.       
  6.     // 2. request  
  7.     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];  
  8.     request.HTTPMethod = @"PUT";  
  9. //    request.HTTPMethod = @"DELETE";  
  10.       
  11.     // 设置用户授权  
  12.     // BASE64编码:一种对字符串和二进制数据进行编码的一种“最常用的网络编码方式”,此编码可以将二进制数据转换成字符串!  
  13.     // 是很多加密算法的底层算法  
  14.     // BASE64支持反编码,是一种双向的编码方案  
  15.     NSString *authStr = @"admin:123";  
  16.     NSString *authBase64 = [NSString stringWithFormat:@"Basic %@", [self base64Encode:authStr]];  
  17.     [request setValue:authBase64 forHTTPHeaderField:@"Authorization"];  
  18.       
  19.     // 3. URLSession  
  20.     NSURLSession *session = [NSURLSession sharedSession];  
  21.       
  22.     // 4. 由session发起任务  
  23.     NSURL *localURL = [[NSBundle mainBundle] URLForResource:@"001.png" withExtension:nil];  
  24.     [[session uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {  
  25.           
  26.         NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];  
  27.           
  28.         NSLog(@"sesult---> %@ %@", result, [NSThread currentThread]);  
  29.     }] resume];  
  30. }  
  31.   
  32. - (NSString *)base64Encode:(NSString *)str  
  33. {  
  34.     // 1. 将字符串转换成二进制数据  
  35.     NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];  
  36.       
  37.     // 2. 对二进制数据进行base64编码  
  38.     NSString *result = [data base64EncodedStringWithOptions:0];  
  39.       
  40.     NSLog(@"base464--> %@", result);  
  41.       
  42.     return result;  
  43. }  

PUT方式与DELETE对应,DELETE用于删除PUT方式上传的文件。


TIPS:session使用注意

* 网络会话 , 方便程序员使用网络服务 .
* : 可以获得当前上传文件的进度 .
* NSURLSession 的任务 默认都是 异步 . ( 在其他线程中工作 )
* Task 是由 会话 发起的 .
* 注意网络请求都要进行出错处理 .
* session 默认是挂起的 , 需要 resume 一下才能启动 .

你可能感兴趣的:(ios,文件上传)