使用Objective-C POST多部分/表单数据

所以这个HTML代码以正确的格式为我提交数据。

<form action="https://www.example.com/register.php" method="post" enctype="multipart/form-data"> Name: <input type="text" name="userName"><BR /> Email: <input type="text" name="userEmail"><BR /> Password: <input type="text" name="userPassword"><BR /> Avatar: <input type="file" name="avatar"><BR /> <input type="submit"> </form> 

我已经研究了很多关于如何在iOS上执行多部分/表单数据POST的文章,但没有一个真正解释如果有正常的参数以及file upload,该怎么做。

你能帮我把代码发布在Obj-C吗?

谢谢!

过程如下:

  1. 使用userNameuserEmailuserPassword参数创build字典。

     NSDictionary *params = @{@"userName" : @"rob", @"userEmail" : @"rob@email.com", @"userPassword" : @"password"}; 
  2. 确定图像的path:

     NSString *path = [[NSBundle mainBundle] pathForResource:@"avatar" ofType:@"png"]; 
  3. 创build请求:

     NSString *boundary = [self generateBoundaryString]; // configure the request NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; [request setHTTPMethod:@"POST"]; // set content type NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; // create body NSData *httpBody = [self createBodyWithBoundary:boundary parameters:params paths:@[path] fieldName:fieldName]; 
  4. 这是上面用来构build请求主体的方法:

     - (NSData *)createBodyWithBoundary:(NSString *)boundary parameters:(NSDictionary *)parameters paths:(NSArray *)paths fieldName:(NSString *)fieldName { NSMutableData *httpBody = [NSMutableData data]; // add params (all params are strings) [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) { [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]]; }]; // add image data for (NSString *path in paths) { NSString *filename = [path lastPathComponent]; NSData *data = [NSData dataWithContentsOfFile:path]; NSString *mimetype = [self mimeTypeForPath:path]; [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:data]; [httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; } [httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; return httpBody; } 
  5. 以上使用了以下实用方法:

     @import MobileCoreServices; // only needed in iOS - (NSString *)mimeTypeForPath:(NSString *)path { // get a mime type for an extension using MobileCoreServices.framework CFStringRef extension = (__bridge CFStringRef)[path pathExtension]; CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL); assert(UTI != NULL); NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType)); assert(mimetype != NULL); CFRelease(UTI); return mimetype; } - (NSString *)generateBoundaryString { return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]]; } 
  6. 然后提交请求。 这里有很多很多的select。

    例如,如果使用NSURLSession ,则可以创buildNSURLSessionUploadTask

     NSURLSession *session = [NSURLSession sharedSession]; // use sharedSession or create your own NSURLSessionTask *task = [session uploadTaskWithRequest:request fromData:httpBody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"error = %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"result = %@", result); }]; [task resume]; 

    或者你可以创build一个NSURLSessionDataTask

     request.HTTPBody = httpBody; NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"error = %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"result = %@", result); }]; [task resume]; 

    上面假设服务器只是返回文本响应。 如果服务器返回JSON,那么最好使用NSJSONSerialization而不是NSString方法initWithData

    同样,我正在使用上面NSURLSession的完成块再现,但也可以使用更丰富的基于委托的再现。 但是,这似乎超出了这个问题的范围,所以我会把这个给你。

但是,希望这可以说明这个想法。


如果我没有指出这一点,我会失去工作,比上述更容易,你可以使用AFNetworking ,重复上面的步骤1和2,但只是调用:

 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON; if web service returns JSON, remove this line NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { NSError *error; if (![formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"avatar" fileName:[path lastPathComponent] mimeType:@"image/png" error:&error]) { NSLog(@"error appending part: %@", error); } } progress:nil success:^(NSURLSessionTask *task, id responseObject) { NSLog(@"responseObject = %@", responseObject); } failure:^(NSURLSessionTask *task, NSError *error) { NSLog(@"error = %@", error); }]; if (!task) { NSLog(@"Creation of task failed."); } 

尝试将这个用于不同MIMEtypes的video和图像数据。

 NSDictionary *param; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; // 1. Create `AFHTTPRequestSerializer` which will create your request. AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; NSMutableURLRequest *request; NSData *fileData; if ([objDoc.url containsString:@".mp4"]) { manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"]; [serializer setValue:@"video/mp4" forHTTPHeaderField:@"Content-Type"]; manager.requestSerializer = serializer; } // 2. Create an `NSMutableURLRequest`. NSLog(@"filename =%@",objDoc.url); request= [serializer multipartFormRequestWithMethod:@"POST" URLString:strUrl parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { if ([objDoc.url containsString:@".mp4"]) { [formData appendPartWithFileData:fileData name:@"File" fileName:@"video.mp4" mimeType:@"video/mp4"]; }else{ [formData appendPartWithFileData:fileData name:@"File" fileName:@"image.jpeg" mimeType:@"image/jpeg"]; } } error:nil]; // 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created. self.objeDocument.isUploading = [NSNumber numberWithInt:1]; self.operation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Success %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error!" message:@"The document attached has failed to upload." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; [self.operation cancel]; NSLog(@"Failure %@", error.description); }]; // 4. Set the progress block of the operation. [self.operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite); float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite; }]; // 5. Begin! [self.operation start]; 

使用Objective-C使用多部分或表单数据POST多个图像

 -(void)multipleimageandstring { NSString *urlString=@"URL NAME"; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; NSMutableData *body = [NSMutableData data]; NSString *boundary = @"---------------------------14737809831466499882746641449"; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request addValue:contentType forHTTPHeaderField:@"Content-Type"]; // file float low_bound = 0; float high_bound =5000; float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);//image1 int intRndValue = (int)(rndValue + 0.5); NSString *str_image1 = [@(intRndValue) stringValue]; UIImage *chosenImage1=[UIImage imageNamed:@"Purchase_GUI_curves-12 copy.png"]; NSData *imageData = UIImageJPEGRepresentation(chosenImage1, 90); [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"files\"; filename=\"%@.png\"\r\n",str_image1] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[NSData dataWithData:imageData]]; [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"name\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Nilesh" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"apipassword\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithString:app.password] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"adminId\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithString:app.adminId] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; // close form [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; // set request body [request setHTTPBody:body]; //return and test NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; NSLog(@"%@", returnString); }