Alex Alex - 1 month ago 21
Objective-C Question

AFNetworking: retrieve large image from CGI script, tracking server response

I am sure I am doing this upside down. I am calling a CGI script to get a large image from a private directory on the server. In the code below I am retrieving the image from the server response.

All is working well, but I would like to monitor the response progress to give the user some feedback (I am avoiding a download since recovering the image from the local disk would require additional time).

The uploadProgress track the data sent to the server. Is there any method to monitor to response from the server? It looks like the responseObject is accessible only in the completion handler.

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://www.myurl.com/redirect.html" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSLog(@"Calling server");

[formData appendPartWithFormData:[user_id dataUsingEncoding:NSUTF8StringEncoding] name:@"user"];
[formData appendPartWithFormData:[_imageURL dataUsingEncoding:NSUTF8StringEncoding] name:@"filename"];
} error:nil];

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

manager.responseSerializer = [AFHTTPResponseSerializer serializer];

NSURLSessionUploadTask *uploadTask;
uploadTask = [manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) {

dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"SERVER UPLOAD FRACTION COMPLETED: %f", uploadProgress.fractionCompleted);
});

} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

NSLog(@"Error: %@", error);
NSLog(@"RESPONSE: %@", response);
NSLog(@"responseObject: %@", responseObject);

if (error) {
NSLog(@"Error: %@", error);
} else {

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{

UIImage *image = [UIImage imageWithData:responseObject];

dispatch_sync(dispatch_get_main_queue(), ^{

[myImageView setImage:image];

});
});
}

}];
[uploadTask resume];

Answer

It turns out that AFNetworking has a nice data task method which allows monitoring progress on both, the upload and the download tasks:

dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:

The only caveat is that the downloadProgress block is updated only if the "Content-Length" is present in the response header.

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:urlString parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFormData:[imageURL dataUsingEncoding:NSUTF8StringEncoding] name:@"filename"];
    } error:nil];

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

NSURLSessionDataTask *uploadTask = [manager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"SERVER UPLOAD FRACTION COMPLETED: %f", uploadProgress.fractionCompleted);
        });

    } downloadProgress:^(NSProgress * _Nonnull downloadProgress) {

        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"SERVER DOWNLOAD FRACTION COMPLETED: %f", downloadProgress.fractionCompleted);
        });

    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
       // retrieve the image from the responseObject here
}
Comments