IOS HTTP POST(数据和图像):图像没有得到张贴

我用下面的代码将图像和数据压入服务器。 数据正在发送,但图像未在服务器中接收。 如果在我使用的下面的代码中有错误,是否有人能发现我:

NSString *urlString = [[NSString alloc]initWithString:[NSString stringWithFormat:@"%@action=savesign",MainURL]]; // set up the form keys and values (revise using 1 NSDictionary at some point - neater than 2 arrays) NSArray *keys = [[NSArray alloc] initWithObjects:@"user",@"poll",nil]; NSArray *vals = [[NSArray alloc] initWithObjects:user,pollid,nil]; // set up the request object NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; //Add content-type to Header. Need to use a string boundary for data uploading. NSString *boundary = @"0xKhTmLbOuNdArY"; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; //create the post body NSMutableData *body = [NSMutableData data]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSASCIIStringEncoding]]; //add (key,value) pairs (no idea why all the \r's and \n's are necessary ... but everyone seems to have them) for (int i=0; i<[keys count]; i++) { [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",[keys objectAtIndex:i]] dataUsingEncoding:NSASCIIStringEncoding]]; [body appendData:[[NSString stringWithFormat:@"%@",[vals objectAtIndex:i]] dataUsingEncoding:NSASCIIStringEncoding]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSASCIIStringEncoding]]; } [body appendData:[@"Content-Disposition: form-data; name=\"image\"\r\n" dataUsingEncoding:NSASCIIStringEncoding]]; [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSASCIIStringEncoding]]; [body appendData:[NSData dataWithContentsOfFile:pngFilePath]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSASCIIStringEncoding]]; NSData *imageData = UIImagePNGRepresentation(_Signfield.image); [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"myPngFile.png\"\r\n", _Signfield.image] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:imageData]; [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; // set the body of the post to the reqeust [request setHTTPBody:body]; // make the connection to the web NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; NSLog(returnString); 

这是来自服务器的响应

 {"status":"failure","error":[],"user":0} 

而当我login和检查数据是在那里,但没有形象。

当您通过HTTP POST执行file upload时,通过电报传输的数据如下所示:

 POST /upload HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate, compress Content-Length: 17918 Content-Type: multipart/form-data; boundary=0xKhTmLbOuNdArY Host: example.com User-Agent: HTTPie/0.7.2 --0xKhTmLbOuNdArY Content-Disposition: form-data; name="user" Diphin-Das --0xKhTmLbOuNdArY Content-Disposition: form-data; name="poll" 1 --0xKhTmLbOuNdArY Content-Disposition: form-data; name="image"; filename="myPNGFile.png" Content-Type: image/png [Binary PNG image data not shown] --0xKhTmLbOuNdArY-- 

前七行是描述请求到服务器的HTTP头,包括:

  • HTTP请求方法( POST
  • 正在请求的资源( /upload
  • HTTP协议版本( HTTP/1.1
  • 请求主体Content-Length: 17918Content-Length: 17918
  • 包含在请求体中的数据types( Content-Type: multipart/form-data; boundary=0xKhTmLbOuNdArY

最后一个很有趣。 通过将内容types设置为multipart/form-data ,我们可以将不同的数据types混合到请求主体中。 boundary告诉服务器在请求体中每个表单值是如何分开的。

请求体中的表单值用一个简单的结构来描述:

 --[boundary marker] Content-Disposition: form-data; name="[parameter name]" Content-Type: [parameter value MIME type] [parameter value] 

如果参数值是字母数字,则Content-Type标头是可选的,但对于其他数据types(图像,video,文档等)则是必需的。 请求主体的结束通过一个终止边界标记来标记 ,这个标记是一个带有双连字符后缀的标准边界标记,例如 – --0xKhTmLbOuNdArY-- 。 换行符(\ r \ n)用于分隔内容部分的各个元素。

在多部分POST请求中,可以有其他元素来表示值。 如果你有兴趣,可以在RFC 2388中阅读。

为了从Objective-C上传文件,需要按照上面所述的规范制作请求主体。 我已经从你的问题的代码,并重构它正常工作,并添加了一些解释性说明。

 NSDictionary *params = @{ @"user": user, @"poll": pollid }; NSData *imageData = UIImagePNGRepresentation(_Signfield.image); NSString *urlString = [[NSString alloc]initWithString:[NSString stringWithFormat:@"%@action=savesign",MainURL]]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; NSString *boundary = @"0xKhTmLbOuNdArY"; NSString *kNewLine = @"\r\n"; // Note that setValue is used so as to override any existing Content-Type header. // addValue appends to the Content-Type header NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; NSMutableData *body = [NSMutableData data]; // Add the parameters from the dictionary to the request body for (NSString *name in params.allKeys) { NSData *value = [[NSString stringWithFormat:@"%@", params[name]] dataUsingEncoding:NSUTF8StringEncoding]; [body appendData:[[NSString stringWithFormat:@"--%@%@", boundary, kNewLine] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"", name] dataUsingEncoding:NSUTF8StringEncoding]]; // For simple data types, such as text or numbers, there's no need to set the content type [body appendData:[[NSString stringWithFormat:@"%@%@", kNewLine, kNewLine] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:value]; [body appendData:[kNewLine dataUsingEncoding:NSUTF8StringEncoding]]; } // Add the image to the request body [body appendData:[[NSString stringWithFormat:@"--%@%@", boundary, kNewLine] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"myPngFile.png\"%@", @"image", kNewLine] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Type: image/png"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"%@%@", kNewLine, kNewLine] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:imageData]; [body appendData:[kNewLine dataUsingEncoding:NSUTF8StringEncoding]]; // Add the terminating boundary marker to signal that we're at the end of the request body [body appendData:[[NSString stringWithFormat:@"--%@--", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:body]; NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; NSLog(@"%@", returnString);