request PUT multiparte utilizando AFNetworking

¿Cuál es la forma correcta de codificar una request PUT de varias partes utilizando AFNetworking en iOS? (todavía Objetivo-C, no Swift)

Miré y parece que AFNetworking puede hacer POST multiparte, pero no PUT , ¿cuál es la solución para eso?

Gracias

Puede usar multipartFormRequestWithMethod para crear una request PUT partes con los datos deseados.

Por ejemplo, en AFNetworking v3.x:

 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; NSError *error; NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:@"http://example.com/rest/api/" parameters:@{@"foo" : @"bar"} constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { NSString *value = @"qux"; NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding]; [formData appendPartWithFormData:data name:@"baz"]; } error:&error]; NSURLSessionDataTask *task = [manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error) { NSLog(@"%@", error); return; } // if you want to know what the statusCode was if ([response isKindOfClass:[NSHTTPURLResponse class]]) { NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; NSLog(@"statusCode: %ld", statusCode); } NSLog(@"%@", responseObject); }]; [task resume]; 

Si AFNetworking 2.x, puede usar AFHTTPRequestOperationManager :

 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSError *error; NSURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:@"http://example.com/rest/api/" parameters:@{@"foo" : @"bar"} constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { NSString *value = @"qux"; NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding]; [formData appendPartWithFormData:data name:@"baz"]; } error:&error]; AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"%@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; [manager.operationQueue addOperation:operation]; 

Después de haber ilustrado cómo se puede crear una request de este tipo, vale la pena señalar que los serveres pueden no ser capaces de analizarlos. Cabe destacar que PHP analiza las requestes POST multiparte, pero no las requestes PUT multiparte.

Aquí está el código para Afnetworking 3.0 y Swift que funcionó para mí. ¡Sé que es un hilo antiguo, pero puede ser útil para alguien!

  let manager: AFHTTPSessionManager = AFHTTPSessionManager() let URL = "\(baseURL)\(url)" let request: NSMutableURLRequest = manager.requestSerializer.multipartFormRequestWithMethod("PUT", URLString: URL, parameters: parameters as? [String : AnyObject], constructingBodyWithBlock: {(formData: AFMultipartFormData!) -> Void in formData.appendPartWithFileData(image!, name: "Photo", fileName: "photo.jpg", mimeType: "image/jpeg") }, error: nil) manager.dataTaskWithRequest(request) { (response, responseObject, error) -> Void in if((error == nil)) { print(responseObject) completionHandler(responseObject as! NSDictionary,nil) } else { print(error) completionHandler(nil,error) } print(responseObject) }.resume() 

Puede crear una NSURLRequest construida con el método de request de formulario multiparte de AFHTTPRequestSerialization

 NSString *url = [[NSURL URLWithString:path relativeToURL:manager.baseURL] absoluteString]; id block = ^(id<AFMultipartFormData> formData) { [formData appendPartWithFileData:media name:@"image" fileName:@"image" mimeType:@"image/jpeg"]; }; NSMutableURLRequest *request = [manager.requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:url parameters:nil constructingBodyWithBlock:block error:nil]; [manager HTTPRequestOperationWithRequest:request success:successBlock failure:failureBlock]; 

Se me ocurrió una solución que puede manejar cualquier método admitido. Esta es una solución para PUT, pero también puede replacela con POST. Este es un método en una categoría que invoco en la class de model base.

  - (void)updateWithArrayOfFiles:(NSArray *)arrayOfFiles forKey:(NSString *)key params:(NSDictionary *)params success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { id block = [self multipartFormConstructionBlockWithArayOfFiles:arrayOfFiles forKey:key failureBlock:failure]; NSMutableURLRequest *request = [[self manager].requestSerializer multipartFormRequestWithMethod:@"PUT" URLString:self.defaultURL parameters:nil constructingBodyWithBlock:block error:nil]; AFHTTPRequestOperation *operation = [[self manager] HTTPRequestOperationWithRequest:request success:success failure:failure]; [operation start]; } #pragma mark multipartForm constructionBlock - (void (^)(id <AFMultipartFormData> formData))multipartFormConstructionBlockWithArayOfFiles:(NSArray *)arrayOfFiles forKey:(NSString *)key failureBlock:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure { id block = ^(id<AFMultipartFormData> formData) { int i = 0; // form mimeType for (FileWrapper *fileWrapper in arrayOfFiles) { NSString *mimeType = nil; switch (fileWrapper.fileType) { case FileTypePhoto: mimeType = @"image/jpeg"; break; case FileTypeVideo: mimeType = @"video/mp4"; break; default: break; } // form imageKey NSString *imageName = key; if (arrayOfFiles.count > 1) // add array specificator if more than one file imageName = [imageName stringByAppendingString: [NSString stringWithFormat:@"[%d]",i++]]; // specify file name if not presented if (!fileWrapper.fileName) fileWrapper.fileName = [NSString stringWithFormat:@"image_%d.jpg",i]; NSError *error = nil; // Make the magic happen [formData appendPartWithFileURL:[NSURL fileURLWithPath:fileWrapper.filePath] name:imageName fileName:fileWrapper.fileName mimeType:mimeType error:&error]; if (error) { // Handle Error [ErrorManager logError:error]; failure(nil, error); } } }; return block; } 

También usa FileWrapper Interface

  typedef NS_ENUM(NSInteger, FileType) { FileTypePhoto, FileTypeVideo, }; @interface FileWrapper : NSObject @property (nonatomic, strong) NSString *filePath; @property (nonatomic, strong) NSString *fileName; @property (assign, nonatomic) FileType fileType; @end 

Para RAW Body:

NSData * data = someData; NSMutableURLRequest * requeust = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: [self getURLWith: urlService]]];

 [reqeust setHTTPMethod:@"PUT"]; [reqeust setHTTPBody:data]; [reqeust setValue:@"application/raw" forHTTPHeaderField:@"Content-Type"]; NSURLSessionDataTask *task = [manager uploadTaskWithRequest:requeust fromData:nil progress:^(NSProgress * _Nonnull uploadProgress) { } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { }]; [task resume];