iOS实现文件上传功能

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

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

一、 POST方式上传

POST方式提交信息默认使用的是 :

*Content-Type:  application/x-www-form-urlencoded.

*输入中文时,post方式自动进行转义(苹果中自动).

国内的绝大多数网站都采用这种方式上传文件(支持二进制文件)

*Content-Type:multipart/form-data(上传文件)

*都会限制上传文件的大小一般是2M或者更小。

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


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

示例代码:

#import "XNUploadFile.h"

#define kTimeOut 5.0f

@implementation XNUploadFile

/** 分隔字符串 */

static NSString *boundaryStr = @"--";

/** 本次上传标示字符串 */

static NSString *randomIDStr;

/** 上传(php)脚本中,接收文件字段 */

static NSString *uploadID;

- (instancetype)init

{

self = [super init];

if (self) {

/** 本次上传标示字符串 */

randomIDStr = @"itcastupload";

/** 上传(php)脚本中,接收文件字段 */

// 可以咨询公司的网站开发程序员

// 或者用FireBug自己跟踪调试

uploadID = @"uploadFile";

}

return self;

}

#pragma mark - 成员方法. 用NSURLSession来完成上传

- (void)uploadFile:(NSString *)path fileName:(NSString *)fileName completion:(void (^)(NSString *string))completion

{

// 1. url 提示:真正负责文件上传的是php文件,而不是html文件

NSURL *url = [NSURL URLWithString:@"http://localhost/new/post/upload.php"];

// 2. request

NSURLRequest *request = [self requestForUploadURL:url uploadFileName:fileName localFilePath:path];

// 3. session(回话)

// 全局网络回话,为了方便程序员使用网络服务

NSURLSession *session = [NSURLSession sharedSession];

// 4. 数据任务-> 任务都是由回话发起的

/** URLSession的任务,默认都是在其他线程工作的,默认都是异步的 */

[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];

NSLog(@"%@ %@", result, [NSThread currentThread]);

dispatch_async(dispatch_get_main_queue(), ^{

if (completion) {

completion(@"下载完成");

}

});

}] resume];

// NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

//

// id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];

//

// NSLog(@"%@ %@", result, [NSThread currentThread]);

//

// dispatch_async(dispatch_get_main_queue(), ^{

// if (completion) {

// completion(@"下载完成");

// }

// });

// }];

//

// // 5. 启动任务

// [task resume];

}

#pragma mark - 私有方法 : 拼字符串

/** 拼接顶部字符串 */

- (NSString *)topStringWithMimeType:(NSString *)mimeType uploadFile:(NSString *)uploadFile

{

NSMutableString *strM = [NSMutableString string];

[strM appendFormat:@"%@%@\n", boundaryStr, randomIDStr];

[strM appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\n", uploadID, uploadFile];

[strM appendFormat:@"Content-Type: %@\n\n", mimeType];

NSLog(@"顶部字符串:%@", strM);

return [strM copy];

}

/** 拼接底部字符串 */

- (NSString *)bottomString

{

NSMutableString *strM = [NSMutableString string];

[strM appendFormat:@"%@%@\n", boundaryStr, randomIDStr];

[strM appendString:@"Content-Disposition: form-data; name=\"submit\"\n\n"];

[strM appendString:@"Submit\n"];

[strM appendFormat:@"%@%@--\n", boundaryStr, randomIDStr];

NSLog(@"底部字符串:%@", strM);

return [strM copy];

}

/** 指定全路径文件的mimeType */

- (NSString *)mimeTypeWithFilePath:(NSString *)filePath

{

// 1. 判断文件是否存在

if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {

return nil;

}

// 2. 使用HTTP HEAD方法获取上传文件信息

NSURL *url = [NSURL fileURLWithPath:filePath];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 3. 调用同步方法获取文件的MimeType

NSURLResponse *response = nil;

[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];

return response.MIMEType;

}

/** 上传文件网络请求 */

- (NSURLRequest *)requestForUploadURL:(NSURL *)url uploadFileName:(NSString *)fileName localFilePath:(NSString *)filePath

{

// 0. 获取上传文件的mimeType

NSString *mimeType = [self mimeTypeWithFilePath:filePath];

if (!mimeType) return nil;

// 1. 拼接要上传的数据体

NSMutableData *dataM = [NSMutableData data];

[dataM appendData:[[self topStringWithMimeType:mimeType uploadFile:fileName] dataUsingEncoding:NSUTF8StringEncoding]];

// 拼接上传文件本身的二进制数据

[dataM appendData:[NSData dataWithContentsOfFile:filePath]];

[dataM appendData:[[self bottomString] dataUsingEncoding:NSUTF8StringEncoding]];

// 2. 设置请求

NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeOut];

// 1> 设定HTTP请求方式

requestM.HTTPMethod = @"POST";

// 2> 设置数据体

requestM.HTTPBody = dataM;

// 3> 指定Content-Type

NSString *typeStr = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", randomIDStr];

[requestM setValue:typeStr forHTTPHeaderField:@"Content-Type"];

// 4> 指定数据长度

NSString *lengthStr = [NSString stringWithFormat:@"%@", @([dataM length])];

[requestM setValue:lengthStr forHTTPHeaderField:@"Content-Length"];

return [requestM copy];

}

注意:POST上传时,是不允许重名的.(否则出错)

二、 PUT方式上传

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

用PUT方式上传的好处:(需要身份验证)

*不用像POST一样,拼一堆字符串.

*直接base64编码一下身份验证, session的upload一调用就行了.

*没有文件大小限制.

*即时通讯里面用的多.(发图片/发语音)

- (void)putFile

{

// 1. url 最后一个是要上传的文件名

NSURL *url = [NSURL URLWithString:@"http://localhost/uploads/abcd"]; //abcd为文件名

// 2. request

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

request.HTTPMethod = @"PUT";

// request.HTTPMethod = @"DELETE";

// 设置用户授权

// BASE64编码:一种对字符串和二进制数据进行编码的一种“最常用的网络编码方式”,此编码可以将二进制数据转换成字符串!

// 是很多加密算法的底层算法

// BASE64支持反编码,是一种双向的编码方案

NSString *authStr = @"admin:123";

NSString *authBase64 = [NSString stringWithFormat:@"Basic %@", [self base64Encode:authStr]];

[request setValue:authBase64 forHTTPHeaderField:@"Authorization"];

// 3. URLSession

NSURLSession *session = [NSURLSession sharedSession];

// 4. 由session发起任务

NSURL *localURL = [[NSBundle mainBundle] URLForResource:@"001.png" withExtension:nil];

[[session uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"sesult---> %@ %@", result, [NSThread currentThread]);

}] resume];

}

- (NSString *)base64Encode:(NSString *)str

{

// 1. 将字符串转换成二进制数据

NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];

// 2. 对二进制数据进行base64编码

NSString *result = [data base64EncodedStringWithOptions:0];

NSLog(@"base464--> %@", result);

return result;

}

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

TIPS:session使用注意

*网络会话, 方便程序员使用网络服务.

*如:可以获得当前上传文件的进度.

*NSURLSession的任务, 默认都是异步的.(在其他线程中工作)

*Task是由会话发起的.

*注意网络请求都要进行出错处理.

*session默认是挂起的, 需要resume一下才能启动.

以上是 iOS实现文件上传功能 的全部内容, 来源链接: utcz.com/z/353096.html

回到顶部