Multipage PUT request using AFNetworking

What is the correct way to encode a multi-page PUT request using AFNetworking in iOS? (still Objective-C, not Swift)

I looked and it seems AFNetworking can do multipart POST , but not PUT , what is this solution?

thanks

+8
rest ios objective-c afnetworking afnetworking-2
source share
6 answers

You can use multipartFormRequestWithMethod to create a multipart PUT request with the required data.

For example, in 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]; 

If AFNetworking 2.x, you can use 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]; 

Having demonstrated how you can create such a query, it is worth noting that the servers will not be able to analyze them. Notably, PHP parses multiple POST requests, but not multipart PUT .

+14
source share

Here is the code for Afnetworking 3.0 and Swift that worked for me. I know his old thread, but it can be convenient for someone!

  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() 
+3
source share

You can create an NSURLRequest built using the AFHTTPRequestSerialization request AFHTTPRequestSerialization for multiple form forms

 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]; 
0
source share

I came up with a solution that any supported method can handle. This solution is for PUT, but you can also replace it with POST. This is the method in the category that I call in the base class of the model.

  - (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; } 

It also uses the 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 
0
source share

For 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]; 
0
source share

.h

 + (void)PUT:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock success:(void (^)(NSURLResponse *response, id responseObject))success failure:(void (^)(NSURLResponse * response, NSError *error))failure error:(NSError *__autoreleasing *)requestError; 

.m:

 + (void)PUT:(NSString *)URLString parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock success:(void (^)(NSURLResponse * _Nonnull response, id responseObject))success failure:(void (^)(NSURLResponse * _Nonnull response, NSError *error))failure error:(NSError *__autoreleasing *)requestError { NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"PUT" URLString:(NSString *)URLString parameters:(NSDictionary *)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block error:(NSError *__autoreleasing *)requestError]; AFURLSessionManager *manager = [AFURLSessionManager sharedManager];//[AFURLSessionManager manager] NSURLSessionUploadTask *uploadTask; uploadTask = [manager uploadTaskWithStreamedRequest:(NSURLRequest *)request progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error) { failure(response, error); } else { success(response, responseObject); } }]; [uploadTask resume]; } 

Just like classic aftertting. Put it in your network work. Util :)

0
source share

All Articles