post&上传代码实现
post传递普通账号密码时候,数据包含在请求体中。在上传文件的时候同样如此。当一个服务器接收到上传指令。假设发送一个简单的txt,此时客户端整体发送给服务器的数据包含两大类:
两者加起来就是完整的发送给服务器的二级制数据的组成格式。由于W3C制定了标准格式,并且apple没有封装。所有如果在IOS中,实现POST上传文件,需要拼接数据成上述格式才能实现(java .net都封装了...)。
但是IOS有第三方框架。AFN能够实现同时上传一个文件,有时候的格式还无法上传。ASI能实现多个上传(MRC--2012停止更新--设计的目标平台是IOS2.0/3.0)。
番外篇:
在以前的服务器中,服务器价格往往昂贵。网站基本会限制上传或者批量上传。例如照片不能超多多少M,只能单张传递(年轻的QQ控件)。随着现今云服务器的普及,软件开发商希望获得更多的用户数据,所以上传下载批量实现在移动互联端也很重要。
此时 出现了一种交 UGC(用户生成内容)的应用。(网易新闻,糗事百科,微博等等等)---想要把软件做好,就要鼓励用户生成内容。(这就是评论,弹幕的魅力),官方软件总有力竭的一天。而用户是无穷的。各类微博基本都是靠名人效应吸引大家,然后数据大部分来自用户。
垂直社交软件:三大移动巨头的用户是很多很多的。而这个世界上的用户是无穷的。垂直社交app现在也是很高大上。骑行,羽毛球,爬山,穷游,酒吧。一群人的圈子不会仅限于微信贴吧。有专属的权威的APP,大家肯定更喜欢用。
继续POST:
如上content-Type为Xcode实现上传必须拼接的数据,两个加起来就是一个完整的二进制数据。
盗用刀哥一段总结,已经超越了我网络工程的忧郁专门门槛
1 Content-Type: multipart/form-data; boundary(分隔线)=(可以随便写,ASCII,字母和数字) 2 3 ## 注释 4 5 * userfile => 负责上传文件脚本中的 字段名,开发的时候,可以咨询后端程序员 6 * filename => 将文件保存在服务器上的文件名称 7 * Content-Type: 客户端告诉服务器上传文件的文件类型 8 - 大类型/小类型 9 - text/plain 10 - image/jpg 11 - image/png 12 - image/gif 13 - text/html 14 - application/json 15 16 - application/octet-stream(8进制流),如果不想告诉服务器具体的文件类型,可以使用这个 Content-Type 17 18 * 注意:每一行末尾需要有一定的 \r\n 19 * 提示:有些服务器可以直接使用 \n,但是新浪微博如果使用 \n 上传文件,服务器会返回“没有权限”的错误! 20 21 ## 上传单个文件 22 23 --boundary\r\n 24 Content-Disposition: form-data; name="userfile"; filename="aaa.txt"\r\n 25 Content-Type: application/octet-stream\r\n\r\n 26 27 要上传文件的二进制数据 28 29 \r\n--boundary-- 30 31 32 ## 上传多个文件 33 34 * 有些服务器可以在上传文件的同时,提交一些文本内容给服务器 35 * 典型应用:新浪微博,上传图片的同时,发送一个微博! 36 37 38 Content-Type: multipart/form-data; boundary=boundary 39 40 // ------ 以下内容,是提价给服务器的二进制数据格式 41 --boundary\r\n 42 Content-Disposition: form-data; name="userfile[]"; filename="aaa.txt"\r\n 43 Content-Type: application/octet-stream\r\n\r\n 44 45 二进制数据 46 \r\n 47 --boundary\r\n 48 Content-Disposition: form-data; name="userfile[]"; filename="aaa副本.txt"\r\n 49 Content-Type: application/octet-stream\r\n\r\n 50 51 二进制数据 52 \r\n 53 --boundary\r\n 54 // status 是脚本文件接收参数的名称 55 Content-Disposition: form-data; name="status"\r\n\r\n 56 57 二进制数据 58 \r\n 59 --boundary-- 60 // ------
OC实现:
(1)三步完成请求发送
(2)单独封装请求体拼接方法
(3)触摸调动方法
1 static NSString *boundary = @"aixiaoxin"; 2 3 - (void)upLoad:(NSString *)field fileName:(NSString *)fileName data:(NSData *)data{ 4 5 // 发送请求 6 NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/post/upload.php"]; 7 8 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:10.0]; 9 10 // 设置请求类型 11 request.HTTPMethod = @"POST"; 12 13 // 设置请求体 14 // field是后台要的一个数据(html中依据这个接收) 15 // fileName是要保存的文件名 16 // data就是你要上传的文件的二进制形式 17 request.HTTPBody = [self httpBody:field fileName:fileName data:data]; 18 19 // POST上传此时还要多一个content-type类型,用kvc 20 //Content-Type: multipart/form-data; boundary(分隔线)=(可以随便写,ASCII,字母和数字) 21 [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary] forHTTPHeaderField:@"Content-Type"]; 22 23 // Connection异步主队列发送请求 24 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 25 // 这是一个json 26 NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; 27 NSLog(@"%@",dic); 28 }]; 29 30 31 32 }
1 - (NSData *)httpBody:(NSString *)field fileName:(NSString *)fileName data:(NSData *)data{ 2 3 NSMutableData *dataM = [NSMutableData data]; 4 5 //按照W3C规定的发送给服务器的格式拼接数据 6 /* 7 --boundary\r\n 8 Content-Disposition: form-data; name="userfile"; filename="aaa.txt"\r\n 9 Content-Type: application/octet-stream\r\n\r\n 10 11 要上传文件的二进制数据 12 13 \r\n--boundary-- 14 15 */ 16 17 NSMutableString *strM = [NSMutableString stringWithFormat:@"--%@\r\n", boundary]; 18 [strM appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", field, fileName]; 19 [strM appendString:@"Content-Type: application/octet-stream\r\n\r\n"]; 20 21 [dataM appendData:[strM dataUsingEncoding:NSUTF8StringEncoding]]; 22 [dataM appendData:data]; 23 24 NSString *tail = [NSString stringWithFormat:@"\r\n--%@--", boundary]; 25 [dataM appendData:[tail dataUsingEncoding:NSUTF8StringEncoding]]; 26 27 return [dataM copy]; 28 29 30 }
1 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 2 3 // 测试要上传到服务器的图片转化成二进制 4 NSString *imgStr = [[NSBundle mainBundle]pathForResource:@"1.jpg" ofType:nil]; 5 NSData *imgData = [NSData dataWithContentsOfFile:imgStr]; 6 7 // 调用方法 8 [self upLoad:@"userfile" fileName:@"我是上传的文件.png" data:imgData]; 9 10 }
完成后可看到结论代码:
分析:error = 0说明上传成功
name没有转码,因为设定是中文,但是是.png可以看出确实是一个图片
size大小12260
tmp_name貌似每次名字都不一样,应该是在沙盒中?--不太清楚
type是类型,application/octet-stream说明不需要让服务器知道上传的是什么类型,或者imgae/png来上传png图片也可以
此时在服务器中就可以看到了