NSURLConnection(苹果原生上传单文件)

来源:互联网 发布:看小说软件排行 编辑:程序博客网 时间:2024/05/21 16:00

其实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

通过这坨代码以及我刚才发的简单封装AFN的工具类的代码就能看出,为什么在实际开发中不使用苹果原生的网络访问方法了吧,太繁琐了。但是,第三方框架再牛逼也是基于对苹果原生的封装,如果想要提升自己,还是要从原生一步一步搞懂实现原理,将来才有可能成为像AFN作者这样的大牛,当然,如果只是为了完成开发的网络请求,直接AFN的GET/POST就能满足你的要求了!

0 0
原创粉丝点击