What's the correct way to code a multipart PUT request using AFNetworking on iOS? (still Objective-C, not Swift)
I looked and seems like AFNetworking can do multipart POST but not PUT, what's the solution for that?
Thanks
What's the correct way to code a multipart PUT request using AFNetworking on iOS? (still Objective-C, not Swift)
I looked and seems like AFNetworking can do multipart POST but not PUT, what's the solution for that?
Thanks
You can use multipartFormRequestWithMethod to create a multipart PUT request with desired 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 illustrated how one could create such a request, it's worth noting that servers may not be able to parse them. Notably, PHP parses multipart POST requests, but not multipart PUT requests.
Here is code for Afnetworking 3.0 and Swift that worked for me. I know its old thread but might be handy 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()
You can create an NSURLRequest constructed with the AFHTTPRequestSerialization's multipart form request method
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];
I came up with a solution that can handle any supported method. This is a solution for PUT, but you can replace it with POST as well. This is a method in a category that I call on the base model class.
    - (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;
    }
Aso it uses 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
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];
.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 the classic afnetworking. Put it to your net work Util :)