我使用以下代码将图像和数据推送到服务器中。正在发送数据,但未在服务器中接收图像。如果我在下面的代码中出现错误,有人可以发现我:
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}
当我登录并检查数据是否存在而不是图像时。
答案 0 :(得分:12)
当您通过HTTP POST执行文件上传时,通过网络传输的数据如下所示:
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标头,包括:
POST
)/upload
)HTTP/1.1
)Content-Length: 17918
)Content-Type: multipart/form-data; boundary=0xKhTmLbOuNdArY
)最后一个很有意思。通过将内容类型设置为multipart/form-data
,我们可以在请求正文中包含不同数据类型的混合。 boundary
告诉服务器如何在请求正文中分隔每个表单值。
请求正文中的表单值使用简单的结构进行描述:
--[boundary marker]
Content-Disposition: form-data; name="[parameter name]"
Content-Type: [parameter value MIME type]
[parameter value]
如果参数值是字母数字,则Content-Type标头是可选的,但对于其他数据类型(图像,视频,文档等),它是必需的。请求体的结束由终止边界标记发信号通知,终止边界标记是标准边界标记,后缀为双连字符,例如--0xKhTmLbOuNdArY--
。新行字符(\ r \ n)用于分隔内容部分的各种元素。
多部分POST请求中的表单值可以有其他元素。如果您有兴趣,可以在RFC 2388中阅读相关内容。
为了从Objective-C上传文件,您需要将请求主体设计为上面列出的规范。我从您的问题中获取了代码并重构了它以正确运行&amp;在此过程中添加了一些解释性说明。
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);