How do you implement an upload file from disk with additional information (in my case caption
& channel_id
) using AFNetworking 3.0 uploadTaskWithRequest:fromFile:progress:completionHandler
to take advantage of the new background session uploading?
I'm open to alternative solution if it works with AFNetworking and the background file uploading.
Here's what I've tried which the server responds with 400 bad request or 500 internal processing error (doing a multipart form post in cURL works):
@property (nonatomic, strong) AFURLSessionManager *uploadSession;
// Configured uploadSession as backgroundSession configuration with couple of headers
- (void)uploadMediafileFilename:(NSString *)filename
filenameWithPath:(NSString *)filenameWithPath
progress:(void ( ^ ) ( NSProgress *uploadProgress ))progress
caption:(NSString *)caption
channel:(NSString *)channelId
completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionBlock {
// ---------
// Create Request Method #1
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@/", kAPIBaseURL, kAPIMediafilesURL]]];
// Tried dictionary to JSON in body. Also tried a params string version.
NSDictionary *dict = @{ @"channel_id" : channelId,
@"mediafile" : @{ @"filename" : filename, @"caption" : caption } };
request.HTTPBody = [NSKeyedArchiver archivedDataWithRootObject:dict];
request.HTTPMethod = @"POST";
// ---- OR ----
// Create Request Method #2
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:[NSString stringWithFormat:@"%@%@", kAPIBaseURL, kAPIMediafilesURL] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFormData:[caption dataUsingEncoding:NSUTF8StringEncoding] name:@"mediafile[caption]"];
[formData appendPartWithFormData:[channelId dataUsingEncoding:NSUTF8StringEncoding] name:@"channel_id"];
[formData appendPartWithFileURL:fileURL name:@"mediafile[filename]" fileName:filename mimeType:@"image/jpeg" error:nil];
} error:nil];
// ----------
NSURL *fileURL = [NSURL fileURLWithPath:filenameWithPath];
[request setValue:[self token] forHTTPHeaderField:kTokenHeaderField];
// Tried using uploadTaskWithRequest - prefer due to its background capabilities. Also tried uploadTaskWithStreamedRequest.
NSURLSessionUploadTask *uploadTask = [self.uploadSession uploadTaskWithRequest:request fromFile:fileURL progress:progress completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"%@", [response description]);
}
if (completionBlock) {
completionBlock(response, responseObject, error);
}
}];
[uploadTask resume];
}
I got this to work using the following:
AFURLSessionManager *uploadSession
as a
defaultSessionConfiguration
. NSMutableURLRequest
using method #2 above. uploadTaskWithStreamedRequest:progress:completionHandler:
Bottomline: backgroundSessionConfiguration
does not work with streamed multi-part form and I could not get additional data to be included with uploadTaskWithRequest:fromFile:
.