使用HTTP POST上传多个文件

7

我在使用iPhone应用程序上传文件时遇到了问题。

我正在向我的Web服务发送一个带有所有必要参数的HTTP POST请求。我正在发送两个文件,一个是图像,另一个是音频。图像正在上传,但音频没有上传成功。当我跟踪我的Web服务时,它只显示图像字段作为已上传的文件。它没有显示音频也已经上传。

我的代码如下:

NSString *urlString = [NSString stringWithFormat:ADD_LEAD_API_URL];

NSMutableURLRequest *postRequest =  [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];



// change type to POST (default is GET)
[postRequest setHTTPMethod:@"POST"];


// just some random text that will never occur in the body
NSString *stringBoundary = @"0xKhTmLbOuNdArY---This_Is_ThE_BoUnDaRyy---pqo";

// header value
NSString *headerBoundary = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",stringBoundary];

// set header
[postRequest addValue:headerBoundary forHTTPHeaderField:@"Content-Type"];

// create data
NSMutableData *postBody = [NSMutableData data];



[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"userId\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[appDelegate.objCurrentUser.userId dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];     


// message part
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"firstName\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[firstName dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

/*** My rest of string parameters are successfully added to request ***/


// media part
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"imageUrl\"; filename=\"dummy.jpg\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"Content-Type: image/jpeg\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"Content-Transfer-Encoding: binary\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    // get the image data from main bundle directly into NSData object

UIImage *img= leadImage;
NSData *imageData= UIImageJPEGRepresentation(img,90);

[postBody appendData:imageData];

// Image is being uploaded

[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"recordSoundUrl\"; filename=\"%@\"\r\n", self.recordingPath] dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"Content-Type: application/octet-stream\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData:[@"Content-Transfer-Encoding: binary\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];


NSData *soundData = [NSData dataWithContentsOfFile:[appDelegate.documentDir stringByAppendingPathComponent:self.recordingPath]];
[postBody appendData:soundData];
[postBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

// final boundary
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];

// add body to post
[postRequest setHTTPBody:postBody];

// Asynch request
NSURLConnection *conn = [NSURLConnection connectionWithRequest:postRequest delegate:self];

如果我不上传图片,那么它会获取音频。因此,我只能发送一个文件作为请求。请帮助我并告诉我是否有任何错误。 提前感谢您的帮助。

嗨 Kapil,我遇到了同样的问题。你能帮我解决一下吗? - iOS Monster
你在做什么?你是在尝试使用我之前的方法上传多个文件吗?如果是这样,在添加图像数据的行后:[postBody appendData:imageData];,请将[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];替换为[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];...希望这可以帮到你。 - Kapil Choubisa
如果这不起作用,请让我知道。我一直在这里帮忙。 - Kapil Choubisa
Kapil,我尝试了你的解决方案,但对我没有用,所以我选择使用ASIHTTPRequest。无论如何还是谢谢。 - iOS Monster
嗨,我正在使用这种方法在Facebook上发布内容。对于单张照片来说,这个方法还可以。但是我想一次上传多张照片,而这种方法只能上传一张图片,即使我已经添加了2-3张图片。在iOS上,有更好的多图上传方式吗? - geekay
3个回答

7

很简单。只需形成多部分主体即可。假设您要上传文件和常规参数,请使用“params”字典:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: urlString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:54.0];

NSMutableData* body = [NSMutableData data];

NSString* boundary = [NSString randomStringWithLength:64];
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];
NSData *boundaryData = [[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding];

[params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
   [body appendData:boundaryData];
    // I use special simple class to distinguish file params
   if( [obj isKindOfClass:[FileUpload class]] ) {
        // File upload
        [body appendData: [[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n\r\n", key, [obj localName]] dataUsingEncoding:NSUTF8StringEncoding]];
        [body appendData: [obj loadData]]; // It just return NSData with loaded file in it
        [body appendData: [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    }
    else {
        // Regular param
        [body appendData: [[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n", key, obj] dataUsingEncoding:NSUTF8StringEncoding]]
    }
}];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

[request setValue:[NSString stringWithFormat:@"%d", [body length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:body];

现在你可以以任何方式进行调度:
[NSURLConnection sendAsynchronousRequest:request
                                   queue:queueOfYourChoice
                       completionHandler:^(NSURLResponse *response, NSData *rdata, NSError *error) 

FileUpload类相对简单:它由url /文件名构建,将此名称作为方法提供,并将二进制内容加载到NSData *中。出于清晰起见,我不会列出它,但如果需要,我可以添加。


这里的params是什么意思? - kshitij godara
这是一个带有您请求参数的字典。 - sergeych

2

您考虑过使用ASIHTTPRequestASINetworkQueue来发送多个文件吗?

更新:根据下面的评论,ASIHTTPRequest已不再维护。使用此框架时请小心。其他选择包括MKNetworkKitAFNetworking


是的,这也是一个不错的选择,但我不能改变我的整个代码。只需在添加图像数据后添加 "\r\n" 即可完成相同的代码。无论如何感谢。 - Kapil Choubisa
1
请注意,自此发布时间至今,ASIHTTPRequest已被弃用。任何阅读此内容的人都应适当谨慎地使用。 - Steven Fisher

0

你在设置边界时可能会遇到问题。

使用这个作为边界

NSString boundary = [NSString stringWithString:@"---------------------------14737809831466499882746641449"];

并使用这个

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

用这个代替

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

1
这是一年前的帖子。如果您看到我自己问题的评论,我已经提到了如何解决我的问题,并且与您的答案相同。我已经使用您告诉我的方法解决了这个问题(您可以查看我的评论)。无论如何,还是谢谢您试图帮助我。 - Kapil Choubisa
1
你应该接受最正确的答案;你应该能够移动你接受的答案。 - Steven Fisher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接