iOS, загрузить файл с мультиформатными данными

Я хотел бы загрузить файл на HTTP-сервер. Я делаю это так:

NSString *boundary = @"*****"; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:@"http://someUploadScript.php"]]; [request setHTTPMethod:@"POST"]; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; [request setValue:@"Keep-Alive" forHTTPHeaderField: @"Connection"]; dispatch_async(queue, ^{ NSMutableData *postbody = [NSMutableData data]; [postbody appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"video.mp4\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; NSString* outputPath = @"somePathToFile"; NSData *data = [NSData dataWithContentsOfFile:outputPath]; [postbody appendData:data]; [postbody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:postbody]; previousBytesWritten = 0; connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; }); 

Я хотел бы отправить некоторые дополнительные данные, например. подал «пользователь» с «userId» значением. Я хотел бы отправить какой-то массив вроде:

 video[user] = "userId" video[file] = //file bytes 

Я знаю, что могу сделать это, используя HTTP multipartform-data, но я действительно не знаю, как и я не понимаю, как это работает. Может кто-нибудь объяснить мне, как я могу это сделать и как это работает?

Solutions Collecting From Web of "iOS, загрузить файл с мультиформатными данными"

Попробуйте что-то вроде этого:

 NSMutableData *postbody = [NSMutableData data]; [postbody appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"video.mp4\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; NSString* outputPath = @"somePathToFile"; NSData *data = [NSData dataWithContentsOfFile:outputPath]; [postbody appendData:data]; [postbody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; // Adding one more field: // append boundary [postbody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; // setting up form-data header, if it is text no 'filename' needed [postbody appendData:[@"Content-Disposition: form-data; name=\"userId\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; // appending userId value [postbody appendData:[_userId dataUsingEncoding:NSUTF8StringEncoding]]; // Ending boundary [postbody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [postbody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:postbody]; 

Также не забудьте добавить в заголовок HTTP-заголовок Content-Length.

AFNetowrking – это удобное решение на сегодняшний день. Это можно легко достичь.

Для iOS 6 и выше

 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSDictionary *parameters = @{@"foo": @"bar"}; NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; [manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileURL:filePath name:@"image" error:nil]; } success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Success: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; 

Если проект лучше подходит для iOS 7 и выше.

 NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil]; } error:nil]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; NSProgress *progress = nil; NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { if (error) { NSLog(@"Error: %@", error); } else { NSLog(@"%@ %@", response, responseObject); } }]; [uploadTask resume]; 

над образцами кода из документации библиотеки. Что можно найти на странице https://github.com/AFNetworking/AFNetworking

Вы можете использовать мою библиотеку для такого сетевого запроса:

 WebRequest *request = [[WebRequest alloc] initWithPath:@"...documents/create.json"]; request.delegate = delegate; request.notificationName = @"NotificationDocumentUploaded"; NSMutableData *body = [NSMutableData data]; NSString *boundary = @"TeslaSchoolProjectFormBoundary"; [body appendPartName:@"document[name]" value:@"Test" boundary:boundary]; [body appendPartName:@"document[description]" value:@"This is a description" boundary:boundary]; [body appendPartName:@"document[category]" value:@"Drama" boundary:boundary]; ... [body appendPartName:@"commit" value:@"Save" boundary:boundary]; NSData *fileData = [[NSData alloc] initWithContentsOfURL:someFileURL]; [body appendPartFile:fileName name:@"document[file]" data:fileData mimeType:mimeType boundary:boundary]; [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:body]; NSString *bodyLength = [NSString stringWithFormat:@"%lu",(unsigned long)[body length]]; [request addValue:bodyLength forHTTPHeaderField:@"Content-Length"]; // optional [request addValue:@"gzip,deflate,sdch" forHTTPHeaderField:@"Accept-Encoding"]; [request addValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"]; [request addValue:@"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" forHTTPHeaderField:@"Accept"]; [request addValue:@"en-US,en;q=0.8,hr;q=0.6,it;q=0.4,sk;q=0.2,sl;q=0.2,sr;q=0.2" forHTTPHeaderField:@"Accept-Language"]; [request setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"]; [request setHTTPMethod:@"POST"]; [WebRequestProcessor process:request]; 

Делегат настроен для уведомления о ходе загрузки.