AFNetworking check progress - iphone

I'm using the AFNetworking framework to download files and write them to the local file system.
But since the files can be quite big I want to add a UIProgressView, but I can't seem to find any method that gets updated with the progress.
I see people talking about setProgressBlock, but I can't find any information about this in the docs: http://afnetworking.org/Documentation/Classes/AFHTTPRequestOperation.html
Is there a method that does this? I'm just using AFHTTPRequestOperation to download the files.

refer a following code. this is a some file download using a AFNetworking Code.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://blahblah.com/blahblah.mp3"]];
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [paths objectAtIndex:0] stringByAppendingPathComponent:#"blahblah.mp3"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
[operation setDownloadProgressBlock:^(NSInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead)
{
myProgressView.progress = (float)totalBytesRead / totalBytesExpectedToRead;
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"downloadComplete!");
}];
[operation start];

The setDownloadProgressBlock method is part of AFURLConnectionOperation, from which AFHTTPRequestOperation inherits - that's why you don't see it in the AFHTTPRequestOperation documentation. The documentation you're after is here:
http://cocoadocs.org/docsets/AFNetworking/1.3.1/Classes/AFURLConnectionOperation.html

Related

AFNetworking AFHTTPRequestOperation responseObject convert to NSXMLParser. The parser doesn't contain the all http information

I have a problem about AFNetworking to get HTML web page.
I had a url:
NSString *url = #"http://www.w3schools.com/";
Also I had a method:
- (void)AFNReturnXMLString:(NSString *)string{
NSURL *url = [NSURL URLWithString:string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
// Make sure to set the responseSerializer correctly
op.responseSerializer = [AFXMLParserResponseSerializer serializer];
op.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// Get XMLParser Object
NSXMLParser *XMLParser = (NSXMLParser *)responseObject;
[XMLParser setShouldProcessNamespaces:YES];
NSLog(#"%#", XMLParser);
// Leave these commented for now (you first need to add the delegate methods)
XMLParser.delegate = self;
[XMLParser parse];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error Fucking: %#", error);
}];
[op start];}
I have already use the NSXMLParser delegate. When I ran the method, the variable "qName" only shows the root <html> and <head> tag, but does not show <body> and <body>'s sub node.
Also I used the following method in the block instead of NSXMLParser object:
// Get HTML String
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", string);
The string shows all the pages content.
Do anyone meet such the problem before?

Downloading a File with AFNetworking

Trying to write a method for my iPhone program that given a URL address to a file, it would download to the iOS App's Documents Directory.
Following AFNetowrking's Documentation, it seems to work fine except that the filename is always some garbage.
I'm using Xcode 5 with AFNetworking 2.0 added to my project. Here's the code that I have so far:
//#import "AFURLSessionManager.h"
//On load (or wherever):
[self downloadFile:#"http://www.irs.gov/pub/irs-pdf/fw4.pdf"];
-(void)downloadFile:(NSString *)UrlAddress
{ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:UrlAddress];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response)
{
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
}
completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
{
NSLog(#"File downloaded to: %#", filePath);
}];
[downloadTask resume];
}
The end result is that the file is successfully downloaded to my documents directory, but with a garbled name:
File downloaded to: file:///Users/myname/Library/Application%20Support/iPhone%20Simulator/7.0/Applications/25188DCA-4277-488E-B08A-4BEC83E59194/Documents/CFNetworkDownload_60NWIf.tmp
The end result I'm expecting:
File downloaded to: file:///Users/myname/Library/Application%20Support/iPhone%20Simulator/7.0/Applications/25188DCA-4277-488E-B08A-4BEC83E59194/Documents/fw4.pdf
I used cocoapods to add AFNetworking to my project:
pod 'AFNetworking', "~> 2.0"
Lastly, what do I need to do to get the progress of the download?
This is the answer I was able to create:
-(void)downloadFile:(NSString *)UrlAddress
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:UrlAddress]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSString *pdfName = #"The_PDF_Name_I_Want.pdf";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:pdfName];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", path);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
NSLog(#"Download = %f", (float)totalBytesRead / totalBytesExpectedToRead);
}];
[operation start];
}
I am open to improvements or suggestions :)
Simply you can replace this line:
return [documentsDirectoryPath URLByAppendingPathComponent:[targetPath lastPathComponent]];
with:
return [documentsDirectoryPath URLByAppendingPathComponent:#"fw4.pdf"];
since [targetPath lastPathComponent] returns something like CFNetworkDownload_60NWIf.tmp

How to avoid delay of webservice(ASIHTTPRequest) response in iPhone?

In my iPhone app handling web service for storing and retrieving data.Now i am using the following code for web service handling.
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"1" forKey:#"id"];
[request setTag:100];
[request setDelegate:self];
[request startAsynchronous];
By this code i got response in 'requestFinished' method.My problem is web service response is very delay(depends upon internet speed).How to make response from web service very fast?Please help me.
I think you want to send json objects by post method..delay is depend on your server(how fast it handle request and response back) but i suggest you to use progress bar and blocks to handle network request..
loadingHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
loadingHUD.labelText = NSLocalizedString(#"Downloading", nil);
loadingHUD.mode=MBProgressHUDModeAnnularDeterminate;
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) lastObject];
// Add your filename to the directory to create your saved file location
NSString* destPath = [documentDirectory stringByAppendingPathComponent:[fileName stringByAppendingString:#".mov"]];
NSURL *url = [NSURL URLWithString:mainURL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:postURL parameters:postRequest];
NSLog(#"postRequest: %#", postRequest);
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:destPath append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"Successfully downloaded file to %#",[[NSString alloc] initWithData:operation.responseData encoding:NSASCIIStringEncoding]);
// Give alert that downloading successful.
NSLog(#"Successfully downloaded file to %#", destPath);
NSLog(#"response: %#", operation.responseString); // Give alert that downloading successful.
// [self.target parserDidDownloadItem:destPath];
loadingHUD.detailsLabelText = [NSString stringWithFormat:#"%# %i%%",#"Downloading",100];
[loadingHUD hide:TRUE];
[DBHelper savePurchaseId:fileName];
[self movieReceived];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
// Give alert that downloading failed
NSLog(#"Error: %#", error);
// [self.target parserDidFailToDownloadItem:error];
[loadingHUD hide:TRUE];
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite)
{
// Progress
progress = ((float)totalBytesWritten) / fileSize;
loadingHUD.progress = progress;
}];
[operation start];
}
We cant control the internet speed due to the different network provider or environment when the client is using your app.
But you can put your web-services to run in background without effecting your main function.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code for webservices calling
dispatch_async(dispatch_get_main_queue(), ^{
//functions after your webservices done, for example reload the table or hide the loading bar.
});
});

AFNetworking: downloading files in queue

I just started using AFNetworking and so far it worked fine for just getting data from the web.
But now I have a list of files that need to be downloaded to the device
for(NSDictionary *issueDic in data)
{
Issue *issue = [[Issue alloc] init];
...
[self getOrDownloadCover:issue];
...
}
getOrDownloadCover:issue checks if a file already exists locally, if it does, it just saves that path, if it doesn't, it downloads the file from a given url
- (void)getOrDownloadCover:(Issue *)issue
{
NSLog(#"issue.thumb: %#", issue.thumb);
NSString *coverName = [issue.thumb lastPathComponent];
NSLog(#"coverName: %#", coverName);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
__block NSString *filePath = [documentsDirectory stringByAppendingPathComponent:coverName];
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
// Cover already exists
issue.thumb_location = filePath;
NSLog(#"issue.thumb_location: %#", filePath);
}
else
{
NSLog(#"load thumb");
// Download the cover
NSURL *url = [NSURL URLWithString:issue.thumb];
AFHTTPClient *httpClient = [[[AFHTTPClient alloc] initWithBaseURL:url] autorelease];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"GET" path:issue.thumb parameters:nil];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
issue.thumb_location = filePath;
NSLog(#"issue.thumb_location: %#", filePath);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"FAILED");
}];
[operation start];
}
}
getOrDownloadCover:issue can be called 20 times in a row, so I would need to put all my requests into a queue, and once the queue is completed, it should still be able to save the path (or just send out a notification, since I already know what the path is)
Any suggestions for this?
Add an NSOperationQueue to an object you can get the instance of at any point in your application, for example in your appDelegate. Then just add the AFHTTPRequestOperation to this queue like:
[[(AppDelegate *) [UIApplication sharedApplication].delegate operartionQueue] addOperation:operation];
Just handle the saving in the completion block, either call a methode from this block on the main thread or post a NSNotification.
To call the main thread use GCD :
dispatch_async(dispatch_get_main_queue(), ^{
// Call any method from on the instance that created the operation here.
[self updateGUI]; // example
});
Not sure if this is helpful but...
Instead of using your own operationQueue you could use AFHTTPClient's operationQueue. Enqueue single operations with enqueueHTTPOperation or enqueue an array of operations with enqueueBatchOperations (I'm recalling these method names from memory, likely off a little).
As far as storing data specific to each operation, you could subclass AFHTTPRequestOperation and set properties for the path you'd like to store. Something like this.

iOS 5 - AFNetworking - Uploading Video

For my app, users will be able to record a video or choose a video from their photo album and through a php script upload the video file to the server. To upload the file to the server, I am using AFNetworking. I originally tried to upload the video from the photo album, but since I could not get that to work I added a video (that I know uploads fine through an html front I made for the php script) into the main bundle.
The code is:
NSString *vidURL = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"mov"];
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:vidURL]];
NSLog(#"The test vid's url is %#.",vidURL);
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL fileURLWithPath: #"http://www.mywebsite.com"]];
NSMutableURLRequest *afRequest = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/upload.php" parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData)
{
[formData appendPartWithFileData:videoData name:#"file" fileName:#"test.mov" mimeType:#"video/quicktime"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest];
[operation setUploadProgressBlock:^(NSInteger bytesWritten,long long totalBytesWritten,long long totalBytesExpectedToWrite)
{
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];
My PHP script runs fine as I am able to upload the same video via an HTML form. The above code fails to get to the setUploadProgressBlock, however.
Does anything stick out as broken to anyone or is there something else I am missing?
Thanks in advance
This is what I used to fix the problem:
httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://www.mysite.com"]];
NSMutableURLRequest *afRequest = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/upload.php" parameters:nil constructingBodyWithBlock:^(id <AFMultipartFormData>formData)
{
[formData appendPartWithFileData:videoData name:#"file" fileName:#"filename.mov" mimeType:#"video/quicktime"];
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:afRequest];
[operation setUploadProgressBlock:^(NSInteger bytesWritten,long long totalBytesWritten,long long totalBytesExpectedToWrite)
{
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {NSLog(#"Success");}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {NSLog(#"error: %#", operation.responseString);}];
[operation start];
Maybe the objects are getting deallocated immediately. Make the AFHTTPClient an instance variable of your class or subclass it and make it a singleton.
More Important: Replace this line:
[operation start];
with:
[httpClient enqueueHTTPRequestOperation:operation];