I need to download a number of files from the server. What is the best way to do it?
All documents are stored in NSMutableArray and for each documents there are two files - the document itself and its change log. So what I do is:
- (void)downloadDocuments:(int)docNumber
{
NSString *urlString;
NSURL *url;
for (int i=0; i<[items count]; i++) {
[progressBar setProgress:((float)i/[items count]) animated:YES];
urlString = [[items objectAtIndex:i] docUrl];
url = [[NSURL alloc] initWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
[self downloadSingleDocument:url];
urlString = [[items objectAtIndex:i] changeLogUrl];
url = [[NSURL alloc] initWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
[self downloadSingleDocument:url];
}
urlString = nil;
url = nil;
[self dismissModalViewControllerAnimated:YES];
}
- (void)downloadSingleDocument:(NSURL *)url
{
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req addValue:#"Basic XXXXXXX=" forHTTPHeaderField:#"Authorization"];
downloadConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}
- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
{
if (conn == downloadConnection) {
NSString *filename = [[conn.originalRequest.URL absoluteString] lastPathComponent];
filename = [filename stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:filename];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
file = [[NSFileHandle fileHandleForUpdatingAtPath:filePath] retain];
if (file)
{
[file seekToEndOfFile];
}
}
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
if (conn == downloadConnection) {
if (file) {
[file seekToEndOfFile];
}
[file writeData:data];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
if (conn==downloadConnection) {
[file closeFile];
}
}
And my problem is that only the last file is downloaded. Any suggestions on what I am doing wrong?
Thanks in advance for help!
The problem is that you "overwrite" the member var "downloadConnection" within your loop with a new instance of NSURLConnection (through method call downloadSingleDocument). Doing this leads to the case that the if-statements within your didReceiveResponse, didReceiveData and connectionDidFinish methods will only evaluate to true with the latest created connection. Try using a list of connections to avoid this.
Related
I want to download the video from the url. I have the video url but don't know how to download it.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
strFileName = #"MyVideo";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://www.youtube.com/v/P9MeXRzKUuA?version=3&f=videos&app=youtube_gdata"]]; //strFileURL is url of your video/image
NSURLConnection *conection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES] autorelease];
[conection start];
[request release];
strFilePath = [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:strFileName] retain];
NSLog(#"file path = %#",strFilePath);
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// create
NSLog(#"file path = %#",strFilePath);
if (![[NSFileManager defaultManager] fileExistsAtPath:strFilePath]) {
[[NSFileManager defaultManager] createFileAtPath:strFilePath contents:nil attributes:nil];
}
file = [[NSFileHandle fileHandleForUpdatingAtPath:strFilePath] retain];// read more about file handle
if (file) {
[file seekToEndOfFile];
}
NSLog(#"response received");
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)receivedata
{
//write each data received
if( receivedata != nil){
if (file) {
[file seekToEndOfFile];
}
[file writeData:receivedata];
NSLog(#"data received");
}
[responseData appendData:receivedata];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
//close file after finish getting data;
NSLog(#"response = %#",[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
[file closeFile];
NSLog(#"file closed");
NSURL *fileURL = [NSURL fileURLWithPath:strFilePath];
NSLog(#"fileurl = %#",fileURL);
[webView loadRequest:[NSURLRequest requestWithURL:fileURL]];
}
In the connectiondidfinishedloading method when I print the response it is null.
Please help me with this
you forgot to initialize the responseData variable. Please do so.
I am new to iPhone developer,
How can i download the epub file from url and store it in Resource folder ?
Here is my code snippet,
- (void)viewDidLoad
{
[super viewDidLoad];
fileData = [NSMutableData data];
NSString *file = [NSString stringWithFormat:#"http://www.google.co.in/url?sa=t&rct=j&q=sample%20epub%20filetype%3Aepub&source=web&cd=2&ved=0CFMQFjAB&url=http%3A%2F%2Fdl.dropbox.com%2Fu%2F1177388%2Fflagship_july_4_2010_flying_island_press.epub&ei=i5gHUIOWJI3RrQeGro3YAg&usg=AFQjCNFPKsV-tieF4vKv7BXYmS-QEvd7Uw"];
NSURL *fileURL = [NSURL URLWithString:file];
NSURLRequest *req = [NSURLRequest requestWithURL:fileURL];
NSURLConnection *conn = [NSURLConnection connectionWithRequest:req delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.fileData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.fileData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSArray *dirArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"%#", [dirArray objectAtIndex:0]);
NSString *path = [NSString stringWithFormat:#"%#", [dirArray objectAtIndex:0]];
if ([self.fileData writeToFile:path options:NSAtomicWrite error:nil] == NO) {
NSLog(#"writeToFile error");
}
else {
NSLog(#"Written!");
}
}
I am not able to see anything in my NSLog.
There is a problem in creation of file path also while writing. you have not specified any filename in the path. In the below line, I have used file name as "filename.txt". Give some proper name and it will write.
NSString *path = [NSString stringWithFormat:#"%#/filename.txt", [dirArray objectAtIndex:0]];
There is a problem in creating URL also. Do it like this,
NSString *file = [NSString stringWithString:#"http://www.google.co.in/url?sa=t&rct=j&q=sample%20epub%20filetype%3Aepub&source=web&cd=2&ved=0CFMQFjAB&url=http%3A%2F%2Fdl.dropbox.com%2Fu%2F1177388%2Fflagship_july_4_2010_flying_island_press.epub&ei=i5gHUIOWJI3RrQeGro3YAg&usg=AFQjCNFPKsV-tieF4vKv7BXYmS-QEvd7Uw"];
NSURL *fileURL = [NSURL URLWithString:file];
You have created your file data with below line.
fileData = [NSMutableData data];
Make it like below,
fileData = [[NSMutableData alloc]init];
OR
self.fileData = [NSMutableData data];
Here iOS releases filedata before your connection delegate get called.
i am using NSURLConnection to download mp3 data from the server , my code is here
- (IBAction)downloadData:(id)sender
{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSURL *url = [[NSURL alloc] initWithString:#"http://viadj.viastreaming.net/start/psalmsmedia/ondemand/Nin%20snehamethrayo.mp3"];
[request setURL:url];
[url release];
url = nil;
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[responseData release];
[connection release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[responseData
length]);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *fileName = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"myFile"];
[responseData writeToFile:fileName atomically:YES];
responseData = nil;
self->imageConnection = nil;
}
am little bit confused about the path given to download. when i click download button i shows "Succeeded! Received 1329 bytes of data" but nothing is downloading. need some help. how will we specify the local path of iPhone to store downloaded data?
- (IBAction)downloadData:(id)sender
{
NSURL *url = [[NSURL alloc] initWithString:#"http://viadj.viastreaming.net/start/psalmsmedia/ondemand/Nin%20snehamethrayo.mp3"];
NSMutableURLRequest *theRequest_to = [NSMutableURLRequest requestWithURL:url];
[url release];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:theRequest_to delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
{
NSString *filepath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"snehamethrayo.mp3"]; // here you can set your filename which you can get from url
[[NSFileManager defaultManager] createFileAtPath:filepath contents:nil attributes:nil];
file = [[NSFileHandle fileHandleForUpdatingAtPath:filepath] retain];// Here file is object of NSFileHandle and its declare in .h File
[file seekToEndOfFile];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[file seekToEndOfFile];
[file writeData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
[file closeFile];
}
No need for any code change I think.Just put an nslog and see...
NSString *fileName = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"myFile"];
NSLog(#"%#",fileName);
That will list the file location like this
/Users/me/Library/Application Support/iPhone Simulator/5.0/Applications/(your app)/Documents/myFile. ie the downloaded file is in your document folder.
note: don't forget to put the file format ie
NSString *fileName = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"myFile.mp3"];
I'm developing a new iPhone application, Here i have parsed a 'csv' file from local, and its working with me. When i try to download the 'csv' file from the server programmatically, it didn't workout for me. Could you please help me?
Loading data from local file (Working fine)
- (void)viewDidLoad
{
[super viewDidLoad];
NSString * file = [[NSBundle bundleForClass:[self class]] pathForResource:#"sample" ofType:#"csv"];
NSStringEncoding encoding = 0;
NSString * csv = [NSString stringWithContentsOfFile:file usedEncoding:&encoding error:nil];
NSArray *fields = [csv CSVComponents];
NSLog(#"fields: %#", fields); //getting the result content
}
Download the file from Server (failed)
-(void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"connectionDidFinishLoading"); //nothing showing here
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *fullName = [NSString stringWithFormat:#"quotes.csv"];
NSString *fullFilePath = [NSString stringWithFormat:#"%#/%#",docDir,fullName];
[receivedData writeToFile:fullFilePath atomically:YES];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"data: %#", data); //nothing showing here
if (receivedData)
[receivedData appendData:data];
else
receivedData = [[NSMutableData alloc] initWithData:data];
}
- (void)loadDatafromURL
{
NSURL *url = [NSURL URLWithString:#"http://download.finance.yahoo.com/d/quotes.csv?s=^GSPC,^IXIC,^dji,^GSPC,^BVSP,^GSPTSE,^FTSE,^GDAXI,^FCHI,^STOXX50E,^AEX,^IBEX,^SSMI,^N225,^AXJO,^HSI,^NSEI&f=sl1d1t1c1ohgv&e=.csv"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
}
Implement this method:
-(void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
You'll find that you're getting an error of
Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0xf663f40 {NSUnderlyingError=0xf663de0 "bad URL", NSLocalizedDescription=bad URL}
I've looked into downloading information this way before, and I think one problem you're having is that separate symbols have to be separated with a "+". Also, when pulling an index, you can't pass the "^" symbol as part of the URL. You have to replace it with "%5E".
So, add this:
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"%#", [error description]);
}
And change your URL to this:
NSString *urlString = #"http://download.finance.yahoo.com/d/quotes.csv?s=^GSPC+^IXIC+^dji+^GSPC+^BVSP+^GSPTSE+^FTSE+^GDAXI+^FCHI+^STOXX50E+^AEX+^IBEX+^SSMI+^N225+^AXJO+^HSI+^NSEI&f=sl1d1t1c1ohgv&e=.csv";
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
Now it works for me! I even checked the output .csv file, and it looks good to go! One full quote per line.
If you plan on fetching more data over the network than this single csv, you could have a look at AFNetworking, it's a great library for doing network operations.
A working solution would then look a bit like this:
- (void)getCSVAsynch {
NSString *unescaped = #"http://download.finance.yahoo.com/d/quotes.csv?s=^GSPC,^IXIC,^dji,^GSPC,^BVSP,^GSPTSE,^FTSE,^GDAXI,^FCHI,^STOXX50E,^AEX,^IBEX,^SSMI,^N225,^AXJO,^HSI,^NSEI&f=sl1d1t1c1ohgv&e=.csv";
NSURL *url = [NSURL URLWithString:[unescaped stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"CSV: %#", [[NSString alloc] initWithBytes:[responseObject bytes] length:[responseObject length] encoding:NSUTF8StringEncoding]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Things go boom. %#", [error localizedDescription]);
}];
[operation start];
}
i want to download file(s) from web server.
Scenario:
As user will select row (file name- user can select 1 or more files to download) and and press download, i am getting URL for each file(all have different URL) and storing into pathArray.
and doing following
-(void)downloadFile {
for (int i = 0; i<[pathArray count]; i++) {
NSURL *fileURL = [NSURL fileURLWithPath:[pathArray objectAtIndex:i]];
NSString *ResultURL = [fileURL absoluteString];
NSURL *url = [[NSURL alloc] initWithString:ResultURL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL: url
cachePolicy: NSURLRequestReloadIgnoringCacheData timeoutInterval: 60.0];
conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if (conn) {
NSLog(#"*************CONNECTED************");
webData = [[NSMutableData data] retain];
NSLog(#"weblength : %d : ", [webData length]);
downloadTag = YES;
} else {
NSLog(#"*************Connection NOT DONE************");
downloadTag=NO;
}
}
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"*************Try to receive data************");
[webData appendData:data];
NSLog(#"weblength : %d : ", [webData length]);
NSLog(#"*************Data Received an append too ***********");
if (downloadTag == YES) {
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
self.documentsDir = [[paths objectAtIndex:0]stringByAppendingPathComponent:#"NewResult.zip" ];
[[NSFileManager defaultManager] createFileAtPath:documentsDir contents:nil attributes:nil];
NSFileHandle *file1 = [NSFileHandle fileHandleForUpdatingAtPath: documentsDir];
[file1 writeData: webData];
NSLog(#"Webdata : %d",[webData length]);
[file1 closeFile];
}
}
if i am not using for loop i.e only one file download then it work fine but not with for loop....its really important for me to solve this issue.
thank you very much
take a look at ASIHTTPRequest, it has a nice queue for downloading and monitoring progress http://allseeing-i.com/ASIHTTPRequest/How-to-use
You're using asynchronous downloads, but the delegate for each download item is the same object, causing all of the downloaded data to get appended to the same file. The way I do it is to have a small Object (DownloadQueueItem) that is the delegate for a single download. When you download another file, you create a new DownloadQueueItem and it handles everything.
Edit:
Q: instead of %i putting by my self i am searching is there any way to create new file every time like if ""NewResult.zip" is exist then create "NewResult1.zip" and so on
A: You could do something like this:
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filename = #"NewResult%#.zip";
for (int i = 0; ; i++) {
NSString *filename = NULL;
if (i == 0) {
filename = [NSString stringWithFormat:filename, #""];
}
else {
filename = [NSString stringWithFormat:filename, [NSString stringWithFormat:#"%i", i]];
}
if (![[NSFileManager defaultManager] fileExistsAtPath:filename]) {
// Save file.
break;
}
}