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];
}
Related
I'd like to download a video from a remote URL and save it to a file in an iPhone app.
I know the video link works, since I have used it from AVPlayer, however, I am unable to download it. The response is always (null).
What is wrong with the following code?
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:someURLString]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:someFilePath append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Successfully downloaded file to %#", [NSURL fileURLWithPath:someFilePath]);
NSLog(#"THE RESPONSE: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[operation start];
Update
I commented out the operation.outputStream line, and this time I got a response. Does this mean that there is something wrong with the file path?
just create a link to that file, then use NSURLConnection to download.
Create a URL connection to download:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:strFileUrl]]; //strFileURL is url of your video/image
NSURLConnection *conection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO] autorelease];
[conec start];
[request release];
Get path of file to save data:
strFilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:strFileName];
Your class must adopt 3 methods of NSURLConnectionDelegate protocol: (please read about Protocol and Delegate)
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// create
[[NSFileManager defaultManager] createFileAtPath:strFilePath contents:nil attributes:nil];
file = [[NSFileHandle fileHandleForUpdatingAtPath:strFilePath] retain];// read more about file handle
if (file) {
[file seekToEndOfFile];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)receivedata
{
//write each data received
if( receivedata != nil){
if (file) {
[file seekToEndOfFile];
}
[file writeData:receivedata];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
//close file after finish getting data;
[file closeFile];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//do something when downloading failed
}
If you want to review you file, use a UIWebview to load it:
NSURL *fileURL = [NSURL fileURLWithPath:strFilePath];
[wvReview loadRequest:[NSURLRequest requestWithURL:fileURL]];
This is what was going wrong.
I was using the url of the video, and as part of the file path.
Why is this wrong? It has backslashes, so I assume iOS was getting confused.
Lesson learned: make sure that the string that you add to a directory to create a file does not have backslashes.
I hope this helps anyone else who makes this silly mistake. :P
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 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.
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"];
This one has me pretty confused. If I put in the following:
NSString *LoginURLString = [NSString stringWithFormat:#"http://dispatch.americantaxi.com:8080/AT/servlet/OnlineOrderServices?command=retrieveCustomerCommonPlaces&customerId=13242134"];
//NSLog output: http://dispatch.americantaxi.com:8080/AT/servlet/OnlineOrderServices?command=retrieveCustomerCommonPlaces&customerId=2314084
And use this in a URL request, it works fine, but I need to make this dynamic, so I have it concatenate the URL string with a new UserID by using the following:
NSString *user = [NSString stringWithFormat:#"%#", [[NSUserDefaults standardUserDefaults]stringForKey:#"CustomerID"]];
//user = [[NSUserDefaults standardUserDefaults] stringForKey:#"CustomerID"];
NSString *LoginURLString = [NSString stringWithFormat:#"http://dispatch.americantaxi.com:8080/AT/servlet/OnlineOrderServices?command=retrieveCustomerCommonPlaces&customerId=%#", user];
//NSLog output: http://dispatch.americantaxi.com:8080/AT/servlet/OnlineOrderServices?command=retrieveCustomerCommonPlaces&customerId=2314084
Here is the rest of my request initializer:
NSString *urlString = LoginURLString;
responseData = [NSMutableData data];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
And the other methods that handle the request:
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[responseData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[responseData appendData:data];
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
// [connection release];
CommonPickUpArray = [[NSMutableArray alloc] init];
CommonLocationInfoArray = [[NSMutableArray alloc] init];
NSString *data = [[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
NSLog(#"%#", data);
}
This request never even starts. I really don't understand why. I have tried to output the two strings to the NSLog and either way they look exactly the same. Can anyone explain? Thanks for your help!
Edit: The Connection didFailWithError method is outputting this:
Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0xf6a6f50 {NSUnderlyingError=0xf6a75d0 "bad URL", NSLocalizedDescription=bad URL}
Output from answer 1:
2012-05-08 13:45:24.959 AmericanTaxi[1295:707] Connection failed with error: bad URL
2012-05-08 13:45:24.960 AmericanTaxi[1295:707] for the URL: (null)
Output of urlString and LoginURLString:
2012-05-08 13:57:40.415 AmericanTaxi[1320:707] LoginURLString: http://dispatch.americantaxi.com:8080/AT/servlet/OnlineOrderServices?command=retrieveCustomerCommonPlaces&customerId=2314084
2012-05-08 13:57:40.417 AmericanTaxi[1320:707] urlstring: http://dispatch.americantaxi.com:8080/AT/servlet/OnlineOrderServices?command=retrieveCustomerCommonPlaces&customerId=2314084
In your didFailWithError, check the URL and see why it is bad by adding this to your didFailWithError delegate:
NSLog(#"Connection failed with error: %#", [error localizedDescription]);
NSLog(#"for the URL: %#", [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
Post the result.