I am using ASIHTTPRequest to download video file from URL in background.
I am displaying the downloads with progress-bar & percentage and I want user can control the downloads like pause & resume.
Below is the code:
-(void)Initiate_Download:(NSString*)urlStr contentID:(NSString*)cid progressBar:(UIProgressView*)progressBar
{
NSLog(#"Initiate_Download for cid:%#",cid);
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlStr]];
NSString *fileName = [NSString stringWithFormat:#"%#.mp4",cid];
NSString *destinationPath = [[self VideoDownloadFolderPath]stringByAppendingPathComponent:fileName];
[request setDownloadDestinationPath:destinationPath];
[request setTemporaryFileDownloadPath:[NSString stringWithFormat:#"%#-part",destinationPath]];
[request setDelegate:self];
NSDictionary *rqstDict = [NSDictionary dictionaryWithObjectsAndKeys:cid,#"cid",urlStr,#"url", nil];
[request setUserInfo:rqstDict];
[request setAllowResumeForFileDownloads:YES];
[request startAsynchronous];
}
//Delegate
- (void)requestStarted:(ASIHTTPRequest *)request1
{
//some code
}
- (void)request:(ASIHTTPRequest *)request1 didReceiveResponseHeaders:(NSDictionary *)responseHeaders
{
//some code
}
- (void)requestFinished:(ASIHTTPRequest *)request1
{
//some code
}
- (void)requestFailed:(ASIHTTPRequest *)request1
{
//some code
}
You need to save the URL and destination path of the request for each request and to pause the request use code :-
[request Cancel];
and to resume the request you need to create another request with same URL and destination path. For example :-
ASIHTTPRequest *requestToResume = [ASIHTTPRequest requestWithURL:url];
[requestToResume setTemporaryFileDownloadPath:tempfilePath];
[requestToResume setDownloadDestinationPath:filePath];
[requestToResume setDelegate:self];
[requestToResume setDownloadProgressDelegate:self];
[requestToResume setUserInfo:dictInfo];
// This file has part of the download in it already
[requestToResume setAllowResumeForFileDownloads:YES];
[requestToResume setDidFinishSelector:#selector(requestDone:)];
[requestToResume setDidFailSelector:#selector(requestWentWrong:)];
[requestToResume startAsynchronous];
In the above code we get the url of the song from the dictionary which was set as userInfo of the request and now we get these details for resuming the request. When we resume the request the file will be downloaded from the point it was paused, hence it will solve the purpose of resuming the file download.
Related
When I start UIActivityIndicatorView using StartAnimating method:
[ActivityIcon startAnimating];
it disable all user interactions so when the user Tap on Cancel button which should abort the download process and hide the UIActivityIndicator it does not work!!!
any suggestions would be appreciated.
Edit:
I am using separate thread to download the files in the background. All progress reporting and UI interaction I made it through:
[self performSelectorOnMainThread:#selector(RefreshScreen:) withObject:nil waitUntilDone:YES];
and RefreshScreen method is the one who interact with the UI elements.
try change this line: [request startSynchronous]; to: [request startAsynchronous];
EDIT
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
I have been using ASIHTTPRequest to fetch the data and i want to cancel the request how i do it??
i do the code just like this..
-(void) serachData{
NSURL *url= [NSURL URLWithString:self.safestring];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setTimeOutSeconds:7200];
[request setDelegate:self];
[request startAsynchronous];
}
- (NSMutableDictionary *)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"requestFinished");
NSString *responseString = [request responseString];
SBJsonParser *json = [[SBJsonParser alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects[jsonobjectWithString:responseString], nil];
NSLog(#"array %#",array);
}
- (void)requestFailed:(ASIHTTPRequest *)request{
NSLog(#"requestFailed");
}
//if i press cancel button(when requestFinished /requestFailed method in process ) then the ASIHTTPRequest fail and finish method Stop /abort! how i do this??
-(IBAction)CancleREquest:(id)sender{
NSLog(#"CancleREquest");
}
Your cancel specific ASIHTTPRequest then :
if(![yourASIHTTPRequest isCancelled])
{
// Cancels an asynchronous request
[yourASIHTTPRequest cancel];
// Cancels an asynchronous request, clearing all delegates and blocks first
[yourASIHTTPRequest clearDelegatesAndCancel];
}
Note : To cancel all ASIHTTPRequest then :
for (ASIHTTPRequest *request in ASIHTTPRequest.sharedQueue.operations)
{
if(![request isCancelled])
{
[request cancel];
[request setDelegate:nil];
}
}
EDIT : Use AFNetworking as ASIHTTPRequest is deprecated as its has not been update since march 2011.
Nice simple version:
for (ASIHTTPRequest *request in ASIHTTPRequest.sharedQueue.operations){
[request cancel];
[request setDelegate:nil];
}
I suggest you to keep a reference to the pending request in an ivar/property of your controller, then send the cancel message to it from your button handler.
//-- in your class interface:
#property (nonatomic, assign) ASIFormDataRequest *request;
....
//-- in your class implementation:
#synthesize request;
.....
-(void) serachData{
NSURL *url= [NSURL URLWithString:self.safestring];
self.request = [ASIFormDataRequest requestWithURL:url];
[self.request setTimeOutSeconds:7200];
[self.request setDelegate:self];
[self.request startAsynchronous];
}
-(IBAction)CancleREquest:(id)sender{
[self.request cancel];
NSLog(#"request Canceled");
}
You have several options when canceling, though; from ASIHTTPRequest docs:
Cancelling an asynchronous request
To cancel an asynchronous request (either a request that was started with [request startAsynchronous] or a request running in a queue you created), call [request cancel]. Note that you cannot cancel a synchronous request.
Note that when you cancel a request, the request will treat that as an error, and will call your delegate and/or queue’s failure delegate method. If you do not want this behaviour, set your delegate to nil before calling cancel, or use the clearDelegatesAndCancel method instead.
// Cancels an asynchronous request
[request cancel]
// Cancels an asynchronous request, clearing all delegates and blocks first
[request clearDelegatesAndCancel];
I am using ASIHTTPRequestfor resuming the downloading of a file gives the error as below and the Resume code is given at the bottom:
Error Domain=ASIHTTPRequestErrorDomain Code=8 "Decompression of /Users/xxxx/Library/Application Support/iPhone Simulator/4.3.2/Applications/6E0D8E0F-08FD-440C-82F6-8E39E219884E/Documents/myPdf.pdf.download failed with code -3" UserInfo=0x4c6a8e0 {NSLocalizedDescription=Decompression of /Users/xxxx/Library/Application Support/iPhone Simulator/4.3.2/Applications/6E0D8E0F-08FD-440C-82F6-8E39E219884E/Documents/myPdf.pdf.download failed with code -3}
Starting download as below:
-(IBAction)startDownload:(id)sender
{
NSURL *url = [NSURL URLWithString:self.sourcePath];
ASIHTTPRequest *req =[[ASIHTTPRequest alloc] initWithURL:url];
[request setDownloadDestinationPath:self.destinationPath];
// This file has part of the download in it already
[request setTemporaryFileDownloadPath:self.temporaryPath];
[req setDownloadProgressDelegate:self];
[req setDelegate:self];
[req startAsynchronous];
self.request = req;
}
and Pause Downloading as below:
-(IBAction)pauseDownload:(id)sender
{
// Cancels an asynchronous request
[request cancel];
// Cancels an asynchronous request, clearing all delegates and blocks first
// [request clearDelegatesAndCancel];
}
and Resume Download as below:
- (IBAction)resumeDownload:(id)sender
{
NSURL *url = [NSURL URLWithString:
self.sourcePath];
ASIHTTPRequest *request1 = [ASIHTTPRequest requestWithURL:url];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSError *err;
NSDictionary *fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath:destinationPath error:&err];
NSLog(#"file Dict: %#", fileDict);
NSLog(#"size: %#",[fileDict valueForKey:NSFileSize]);
NSInteger nSize =[[fileDict valueForKey:NSFileSize] intValue];
// unsigned long long int size1 = [[fileDict valueForKey:NSFileSize] intValue];
NSString *size = [NSString stringWithFormat:#"bytes=%d", nSize];
NSLog(#"file size: %#",size);
[dict setValue:size forKey:#"Range"];
[request1 setRequestHeaders:dict];
// NSString *downloadPath = #"/Users/ben/Desktop/my_work_in_progress.txt";
// The full file will be moved here if and when the request completes successfully
[request1 setDownloadDestinationPath:self.destinationPath];
// This file has part of the download in it already
[request1 setDownloadProgressDelegate:self];
[request1 setDelegate:self];
[request1 setTemporaryFileDownloadPath:self.temporaryPath];
[request1 setAllowResumeForFileDownloads:YES];
[request1 startAsynchronous];
self.request = request1;
//The whole file should be here now.
// NSString *theContent = [NSString stringWithContentsOfFile:downloadPath];
}
And I set the "Range" HTTP header field to the corresponding file size. The same file on server supports download pause, resume on the app http://itunes.apple.com/us/app/download-manager-pro-lite/id348573579?mt=8
How to implement the Resuming a download
Thanks in advance.
You should refer How to Pause and Resume Downloading Files with ASIHTTP Request in iPhone and
ASIHTTPRequest documentation.
Here's a portion of the html code I'm trying to submit the textarea, much this textarea this forum uses to type in questions. It's not working, nothing gets sent and the type of response i get back is
NSHTTPURLResponse: 0x617bb20
Though I managed to get it working for the login except i replaced body=%# with user=%#&pass=%#
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://forums.whirlpool.net.au%#", replyLink]];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setRequestMethod:#"POST"];
[request addRequestHeader:#"Content-Type" value:#"application/xml;charset=UTF-8;"];
[request setPostValue:#"test" forKey:#"body"];
[request setDelegate:self];
[request startAsynchronous];
- (void) requestFinished:(ASIHTTPRequest *)request {
//NSString *responseString = [request responseString];
NSLog(#"Response %d : %#", request.responseStatusCode, [request responseString]);
//NSData *responseData = [request responseData];
}
- (void) requestStarted:(ASIHTTPRequest *) request {
NSLog(#"request started...");
}
- (void) requestFailed:(ASIHTTPRequest *) request {
NSError *error = [request error];
NSLog(#"%#", error);
}
Updated code using ASIHTTPRequest.
ASIHTTPRequest is the way to go here. It's difficult to understand what is exactly wrong with the code you've written (except that it looks like a synchronous request, which is a no-no).
In ASIHTTPRequest you can do this:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:someUrl];
[request setRequestMethod:#"POST"];
[request setPostValue:#"..." forKey:#"user"];
[request setPostValue:#"..." forKey:#"password"];
[request setDelegate:self];
[request startAsyncrhonous];
Then, make sure your class conforms to the ASIHTTPRequestDelegate protocol and implement at the very least, this method:
- (void)requestFinished:(ASIHTTPRequest *)request {
NSLog(#"Response %d ==> %#", request.responseStatusCode, [request responseString]);
}
You can also handle other methods if you choose, such as:
- (void)requestStarted:(ASIHTTPRequest *)request;
- (void)requestFailed:(ASIHTTPRequest *)request;
You can always download the ASIHTTPRequest project from github at http://github.com/pokeb/asi-http-request.
The docs are located at http://allseeing-i.com/ASIHTTPRequest/ and are fantastic.
Hope this helps!
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "JSON.h"
#import "JSONKit.h"
NSURL *url = [NSURL URLWithString:[[NSString stringWithFormat:#"YOUR URL"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setRequestMethod:#"POST"];
[request setPostValue:Email forKey:#"email"];
[request setPostValue:Password forKey:#"password"];
[request setDelegate:self];
[request setUsername:#"signin"];
[request startAsynchronous];
#pragma mark- Request Finish
- (void)requestFailed:(ASIHTTPRequest *)request;
{
NSLog(#"********** RequestFailed **************%#",request.responseString);
[SVProgressHUD dismiss];
}
-(void)requestFinished:(ASIHTTPRequest *)request
{
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *resDict = [parser objectWithString:[request responseString] error:nil];
if ([[request username] isEqualToString:#"signin"])
{
}
[SVProgressHUD dismiss];
}
AFNetworking Files:https://drive.google.com/file/d/0B_RDiggCq5U3enh2WUdKaVlRcGM/view?usp=sharing
ASIHTTPREQUEST files:https://drive.google.com/file/d/0B_RDiggCq5U3LUttRm9WSS1KN2s/view?usp=sharing
Just like to say I got it working :).
For those who wants hints and are in my position, well look for hidden fields in forms or check this site http://www.echoecho.com/htmlforms07.htm
and this post to see what I mean
http://www.iphonedevsdk.com/forum/148450-post14.html
For those who just want a more direct answer keep reading but please read the iphonedevsdk link that was a fundamental step in trying to figure the answer.
As an example one of the hidden fields that were in the html code was:
<input type="hidden" name="version" id="version" value="3">
this would translate to
[request setPostValue:#"3" forKey:#"version"];
"forKey"'s are the "name" field in the html and the "setPostValue" is the value in "html"
you can take the above thinking and apply it to simulate a button press
from
<input type="submit" name="post" id="post" tabindex="56" style="width:150px;font:16px Arial;" value="Post Reply" onc...
to
[request setPostValue:#"submit" forKey:#"post"];
hopefully that helps others :).
Hello
I am sending some values to the server using ASIHTTPRequest. All works fine until yesterday that the requestFinished didnt work. (when the app send the request on the server an activity indicator and a new view added to the main view and when the request finished is removing the views). I added requestFailed to test if is failed and I get this error:
[3438:207] Error Domain=ASIHTTPRequestErrorDomain Code=2 "The request timed out" UserInfo=0x5ad25c0
Its weird because the same code was working fine yesterday. I am sure that they didnt make any changes on the server's side.
this is the code:
- (IBAction)convert:(id)sender{
//Get the email from the textfield
NSString *email1 = email.text;
//Save the last used email to load it on the next app launch
[[NSUserDefaults standardUserDefaults] setValue:email1 forKey:#"email"];
//Get the current URL from webview
NSString *currentURL= webView.request.URL.relativeString;
lbl.text = currentURL;
//Count the length of Label
int strL= [lbl.text length];
//The url that the requests will be send.
NSURL *url = [NSURL URLWithString:#"the website"];
//Indicator and its view are loading on the screen
[ind startAnimating];
[self.view addSubview:indView];
//ASIHTTPRequests
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSString *watch = [lbl.text substringWithRange:NSMakeRange(23,strL-23)];
NSString *link = [NSString stringWithFormat:#"http://youtube.com/%#",watch];
[request setShouldRedirect:YES];
[request setPostValue:watch forKey:#"url"];
[request setPostValue:email1 forKey:#"email"];
[request setPostValue:format forKey:#"format"];
[request setPostValue:quality forKey:#"quality"];
[request setDelegate:self];
[request startAsynchronous];
NSLog(#"%# %# %# %#",watch,email1,format,quality);
click=NO;
}
and this is the requestFinished:
- (void)requestFinished:(ASIFormDataRequest *)request{
NSString *responseString = [request responseString];
NSLog(#"%#",responseString);
NSLog(#"%#",lbl.text);
NSLog(#"requested finished");
[ind stopAnimating];
[indView removeFromSuperview];
[setView removeFromSuperview];
}
Did you try to increase the timeout value on the request? By default it is 10 seconds, you can make it larger by doing this right before the startAsynchronous call:
[request setTimeOutSeconds:60];