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图片也可以

  此时在服务器中就可以看到了

posted @ 2015-07-21 17:14  珍妮是谁  阅读(346)  评论(0编辑  收藏  举报