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一下才能启动.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。