AFNetworking background file upload - objective-c

I want to upload files to my server from my app. The code below is working great when app is active. If I press home button or open another app uploading stops.
I activated background fetch but still not working.
Afnetworking has background support but I cant figure out how I implement this feature to my code.
NSString *str=[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Archive.zip"];
NSDictionary *parameters = #{#"foo": #"bar"};
NSURL *filePath = [NSURL fileURLWithPath:str];
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSData *imageData=[NSData dataWithContentsOfURL:filePath];
NSMutableURLRequest *request =
[serializer multipartFormRequestWithMethod:#"POST" URLString:#"http://url"
parameters:parameters
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:imageData
name:#"image"
fileName:#"Archive.zip"
mimeType:#"application/zip"];
}];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
AFHTTPRequestOperation *operation =
[manager HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure %#", error.description);
}];
[operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
long long totalBytesWritten,
long long totalBytesExpectedToWrite) {
NSLog(#"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];

Change this line
[operation start];
to this
[operation setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
// Handle iOS shutting you down (possibly make a note of where you
// stopped so you can resume later)
}];
[manager.operationQueue addOperation:operation];
You can look at these links
AFHTTPRequestOperation doesn't work after stand by mode
and Alternative for enqueueHTTPRequestOperation in AFNetworking 2.0

Related

AFNetworking 1.x to 3.x migration - get download progress?

I need to download image with progress bar. This is what I've got for in AFNetworking 1.x which is not working for AFNetworking 3.x.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.mediaItem.media_item_hd_url]];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFImageResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
UIImage *image = responseObject;
_image = image;
[self.delegate browserItem:self loaded:1.0 finished:YES];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];
[op setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
CGFloat progress = ((CGFloat)totalBytesRead)/((CGFloat)totalBytesExpectedToRead);
[self.delegate browserItem:self loaded:progress finished:NO];
}];
[[NSOperationQueue mainQueue] addOperation:op];
Finally this is what I could come up with, which is not complete. I have no idea how to use progress in code block.
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.mediaItem.media_item_hd_url]];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(#"File downloaded to: %#", filePath);
// UIImage *image = response;
// _image = image;
[self.delegate browserItem:self loaded:1.0 finished:YES];
}];
[downloadTask resume];
You can get best framework RSNetworkKit which handles all the network call with an ease. It has internally implemented AFNetworking 3.0. It'll gives you download progress in single method either you upload, download.
It has also an enhanced method to show progress on UIImageView.
You can find it here. https://github.com/rushisangani/RSNetworkKit

AFNetworking JSON Request, neither success nor error block called

I'm trying to learn AFNetworking so have written a simple block. I'm trying to retrieve & log the json from the site url below.
NSString *string =
#"http://transportapi.com/v3/uk/bus/stop/490012745J/live.json?api_key=6ee115459cbeccdb902b14d39b61330d&app_id=9deefeb1&group=route";
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *mydict = (NSDictionary *)responseObject;
NSString *key;
for(key in mydict){
NSLog(#" key %#", key);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"ERROR");
}];
But neither the success or the failure block is being called. Can someone point out what I've done wrong?
You're not actually firing the operation you need to add
[[NSOperationQueue mainQueue] addOperation:operation];

Authenticating Users using AfNetworking

I'm trying to authenticate users, but my app keeps on crashing with error 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: urlRequest' what am I doing wrong?
Below is my code
-(IBAction)btnLogin:(id)sender
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager alloc];
NSDictionary *parameters = #{#"email": email.text, #"pass": pword.text};
NSString *str = #"http://www.blablablabla/api2/user.php?type=login";
str = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:#"POST" URLString:str parameters:parameters];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
//[operation setCredential:credential];
[operation setResponseSerializer:[AFJSONResponseSerializer alloc]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", error);
}];
[manager.operationQueue addOperation:operation];
}
You seem to be alloc-ing the AFHTTPRequestOperationManager but does it ever get init'ed?
Also, check the request for nil before passing it to the AFHTTPRequestOperation.
Checking parameters and alloc'ed/created instances for nil can help you tell IMMEDIATELY where a problem is.
Hope this helps.

Trying to read html page from a web site using AFNetworking 2.0

I'm trying to have my app load an HTML web page into a "responseObject" that I can later parse.
Here is my code:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/xhtml+xml"];
NSDictionary *parameters = #{#"ghinno": #"1151213"};
[manager GET:#"http://m.ghin.com/HLR.aspx" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"HTTP: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
...and this is the output. I should be seeing the html from the webpage. Can you help me understand what I am doing wrong?
Ah, the answer lies below...
Essentially, it was an encoding / decoding of the response object that was causing my issues. Here is the final solution: (notice the line beginning with "NSString)...
NSURL *URL = [NSURL URLWithString:#"http://m.ghin.com/HLR.aspx?ghinno=1151213"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", string);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[op start];

AFNetworking upload progress sending SOAP NSData

I am using AFNetworking and would like to upload an NSData object to my server. I am trying to upload to our SOAP server, so I have XML that I have converted to an NSData object. For some reason, the follow does NOT work:
// Back to NSData
NSData *convertedFile = [xml dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:siteConfiguration.soapURL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFormData:convertedFile name:assetCreation.name];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
// Progress
float totalProgress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
progress(totalProgress, totalBytesWritten, totalBytesExpectedToWrite);
if (totalBytesExpectedToWrite == totalBytesWritten) {
completion();
}
}];
[operation start];
But when not using the multipartFormRequestWithMethod block, it DOES work and the file is correctly uploaded, but there is NO progress shown, as the callback is only called once:
// Back to NSData
NSData *convertedFile = [xml dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:siteConfiguration.soapURL];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod: #"POST"];
[request setHTTPBody:convertedFile];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
// Progress
float totalProgress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
progress(totalProgress, totalBytesWritten, totalBytesExpectedToWrite);
if (totalBytesExpectedToWrite == totalBytesWritten) {
MatrixAsset *asset = [[MatrixAsset alloc] init];
completion(asset);
}
}];
[operation start];
It seems that my server really wants to be sent the HTTPBody with my NSData object. Is it possible to do the same with the AFNetworking progress callback?
Ok, I got it working. Looks like I was going about it wrong:
// Setup the connection
NSString *wsdlURL = [NSString stringWithFormat:#"%#?WSDL", siteConfiguration.soapURL];
NSURL *serviceUrl = [NSURL URLWithString:wsdlURL];
NSMutableURLRequest *serviceRequest = [NSMutableURLRequest requestWithURL:serviceUrl];
[serviceRequest setValue:#"text/xml" forHTTPHeaderField:#"Content-type"];
[serviceRequest setHTTPMethod:#"POST"];
[serviceRequest setHTTPBody:[xml dataUsingEncoding:NSUTF8StringEncoding]];
// Operation
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:serviceRequest];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
// Progress
float totalProgress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;
progress(totalProgress, totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Success");
MatrixAsset *asset = [[MatrixAsset alloc] init];
completion(asset);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", error.localizedDescription);
NSLog(#"error: %#", error.localizedFailureReason);
}];
[operation start];
You need SOAPAction to continue:
[serviceRequest setValue:#"SOAP_ACTION_URL" forHTTPHeaderField:#"SOAPAction"];