通过多部分HTTP请求上传ios文本

通过多部分HTTP请求上传ios文本,ios,http-post,nsurlconnection,Ios,Http Post,Nsurlconnection,我正在尝试在iOS中使用多部分表单编码上传文本 我所做的: NSMutableDictionary *params = [NSMutableDictionary new]; [params setObject:@"XXXXX" forKey:@"apikey"]; [params setObject:@"DataAPI" forKey:@"scope"]; [params setObject:@"push" forKey:@"action"]; [para

我正在尝试在iOS中使用
多部分表单编码上传文本

我所做的

    NSMutableDictionary *params = [NSMutableDictionary new];
    [params setObject:@"XXXXX" forKey:@"apikey"];
    [params setObject:@"DataAPI" forKey:@"scope"];
    [params setObject:@"push" forKey:@"action"];
    [params setObject:docName forKey:@"documentName"];
    [params setObject:content forKey:@"content"];
    [params setObject:authToken forKey:@"authtoken"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
    [request setHTTPShouldHandleCookies:NO];
    [request setTimeoutInterval:30];
    [request setHTTPMethod:@"POST"];

    // set Content-Type in HTTP header
    NSString *boundary = @"V2ymHFg03ehbqgZCaKO6jy";

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *body = [NSMutableData data];



    // add params (all params are strings)
    for (NSString *param in params) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];

    }

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];


    // setting the body of the post to the reqeust
    [request setHTTPBody:body];
    NSString *myString = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding];


    NSLog(@"%@",myString);
    // set the content-length
    NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];

    // set URL
    [request setURL:url];


    NSURLResponse *response;
    NSData *POSTReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    NSString *theReply = [[NSString alloc] initWithBytes:[POSTReply bytes] length:[POSTReply length] encoding: NSASCIIStringEncoding];
    NSLog(@"Reply: %@", theReply);
我已尝试通过中提供的信息

问题

    NSMutableDictionary *params = [NSMutableDictionary new];
    [params setObject:@"XXXXX" forKey:@"apikey"];
    [params setObject:@"DataAPI" forKey:@"scope"];
    [params setObject:@"push" forKey:@"action"];
    [params setObject:docName forKey:@"documentName"];
    [params setObject:content forKey:@"content"];
    [params setObject:authToken forKey:@"authtoken"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
    [request setHTTPShouldHandleCookies:NO];
    [request setTimeoutInterval:30];
    [request setHTTPMethod:@"POST"];

    // set Content-Type in HTTP header
    NSString *boundary = @"V2ymHFg03ehbqgZCaKO6jy";

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *body = [NSMutableData data];



    // add params (all params are strings)
    for (NSString *param in params) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];

    }

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];


    // setting the body of the post to the reqeust
    [request setHTTPBody:body];
    NSString *myString = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding];


    NSLog(@"%@",myString);
    // set the content-length
    NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];

    // set URL
    [request setURL:url];


    NSURLResponse *response;
    NSData *POSTReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    NSString *theReply = [[NSString alloc] initWithBytes:[POSTReply bytes] length:[POSTReply length] encoding: NSASCIIStringEncoding];
    NSLog(@"Reply: %@", theReply);
我把日志放在服务器端,下面是我从IOS应用程序收到的信息

名称没有问题。但是,我将
值作为
null

"443" "POST" "/api/private/json/" "content=null&scope=null&action=null&documentname=null&apikey=null"
我的代码

    NSMutableDictionary *params = [NSMutableDictionary new];
    [params setObject:@"XXXXX" forKey:@"apikey"];
    [params setObject:@"DataAPI" forKey:@"scope"];
    [params setObject:@"push" forKey:@"action"];
    [params setObject:docName forKey:@"documentName"];
    [params setObject:content forKey:@"content"];
    [params setObject:authToken forKey:@"authtoken"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
    [request setHTTPShouldHandleCookies:NO];
    [request setTimeoutInterval:30];
    [request setHTTPMethod:@"POST"];

    // set Content-Type in HTTP header
    NSString *boundary = @"V2ymHFg03ehbqgZCaKO6jy";

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *body = [NSMutableData data];



    // add params (all params are strings)
    for (NSString *param in params) {
        [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];

    }

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];


    // setting the body of the post to the reqeust
    [request setHTTPBody:body];
    NSString *myString = [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding];


    NSLog(@"%@",myString);
    // set the content-length
    NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];

    // set URL
    [request setURL:url];


    NSURLResponse *response;
    NSData *POSTReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    NSString *theReply = [[NSString alloc] initWithBytes:[POSTReply bytes] length:[POSTReply length] encoding: NSASCIIStringEncoding];
    NSLog(@"Reply: %@", theReply);
我无法理解这个问题,无论是从服务器端还是从我的代码


谢谢分享您的答案。

您没有附加终止边界

这:

应该是这样的:

[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
for (NSString *param in params) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"\r\n\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
编辑:

实际上,你错过了更多的东西。您没有设置数据的内容类型,并且缺少一些新行

您的循环应该如下所示:

[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
for (NSString *param in params) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:[[NSString stringWithFormat:@"\r\n\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
EDIT2:

下面是一个服务器端代码示例,它正确地处理了相同的请求:

#!/usr/bin/env python

import web

urls = ("/", "Index")
app = web.application(urls, globals())

class Index(object):
    def POST(self):
        x = web.input()
        print x
        print x['apikey']
        print x['scope']
        return 'success'

if __name__ == "__main__":
    app.run()
输出:

<Storage {'scope': u'asd', 'apikey': u'123\r\n'}>
123

asd
127.0.0.1:60044 - - [02/Dec/2013 15:02:55] "HTTP/1.1 POST /" - 200 OK
//这里是编码方法

  • (NSData*)编码字典:(NSDictionary*)字典{ NSMUTABLEARRY*部件=[[NSMUTABLEARRY alloc]init]; for(NSString*字典中的键){ NSString*encodedValue=[[dictionary objectForKey:key]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSString*encodedKey=[key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSString*part=[NSString stringWithFormat:@“%@=%@”,encodedKey,encodedValue]; [零件添加对象:零件]; } NSString*encodedDictionary=[parts Components由字符串连接:@“&”]; 返回[encodedDictionary dataUsingEncoding:NSUTF8StringEncoding]; } //也许这对你完全有帮助
    • 这应该可以解决:

      而不是:

      [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
      

      (终止CRLF是可选的)

      请注意,如果您这样写:

      for (NSString *param in params) {
          [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
          [body appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]
          [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
          [body appendData:[[NSString stringWithFormat:@"%@\r\n", [params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
      }
      [body appendData:[[NSString stringWithFormat:@"\r\n\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
      
      边界分隔符之前的所有内容,例如
      \r\n--
      在概念上属于数据,例如属于参数值

      同样,“破折号边界”(
      --
      )前面的
      CRLF
      属于分隔符

      从概念上讲,第一个分隔符也必须以CRLF开头:

      `CRLF--<boundary>`
      
      前导码
      可以是空的,也可以包含任意数量的CRLF

      主体部分
      ,由MIME头和部分主体数据组成,紧跟在边界之后,但严格来说不是立即:

      <preamble-bytes>CRLF--xyz<transport-padding>CRLF<body-part> 
                      ^~~~~~~~~ delimiter             ^~~~~~~~~~~ MIME headers and data
      
      然后紧接着是
      主体部分
      (从标题开始,然后是数据):

      这四条线可用于每个参数的循环中

      可以按如下方式添加终止分隔符:

      [body appendData:[[NSString stringWithFormat:@"\r\n--%@--", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
      
      终止CRLF是可选的。最后一个CRLF之后的任何字节都属于
      尾声
      ,服务器将忽略这些字节


      参见:RCF 2046。

      我做了更改。但响应相同。在为数据添加内容类型后,结果相同。请参阅我的第二次编辑。刚刚尝试了一个快速python脚本和一个控制台应用程序。看起来问题可能出在服务器端。
      <preamble-bytes>CRLF--xyz<transport-padding>CRLF<body-part> 
                      ^~~~~~~~~ delimiter             ^~~~~~~~~~~ MIME headers and data
      
      [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
      
      [body appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
      [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
      [body appendData:[[NSString stringWithFormat:@"%@", (self.parameters)[key]] dataUsingEncoding:NSUTF8StringEncoding]];
      
      [body appendData:[[NSString stringWithFormat:@"\r\n--%@--", boundary] dataUsingEncoding:NSUTF8StringEncoding]];