I am new to iPhone,
I am currently developing an iPhone app and would like to implement the ability to download file from the url. I have created the UIWebView, when i click on download link in the webview download will start and i am saving that file to a specified folder in the documents directory. but i am unable to see my downloaded file.
Here is my code snippet,
//CAPTURE USER LINK-CLICK in UIwebView.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:DUrl]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
receivedData = [[NSMutableData data] retain];
} else {
NSLog(#"Inform the user that the connection failed.");
}
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data1
{
[receivedData appendData:data1];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
DirPath=[self MyApplicationDocumentDirectory];
[receivedData writeToFile:DirPath atomically:YES];
UIAlertView* Alert = [[UIAlertView alloc] initWithTitle:#"Download Complete !"
message:nil delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[Alert show];
[Alert release];
// release the connection, and the data object
[connection release];
[receivedData release];
}
Any help will be appriciated.
EDIT:
BOOL success =[[NSFileManager defaultManager] fileExistsAtPath:MyDirPath];
if (success)
{
UIAlertView* innerAlert = [[UIAlertView alloc] initWithTitle:#"Already downloaded."
message:#"Do you want to Downlaod again ?" delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Yes",#"No",nil];
[innerAlert show];
[innerAlert release];
}
where to write this condition ?
EDIT Check whether downloaded file already exits in doc dir before writing(saving) downloaded data like this:
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:DirPath error:nil];
BOOL fileExists = NO;
for(NSString *fileName in dirContents)
{
NSString *filePath = [DirPath stringByAppendingPathComponent:fileName];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
if([receivedData isEqualToData:fileData]) //your receivedData here
{
fileExists = YES;
}
}
if(fileExists)
{
NSLog(#"File exists");
}
else
{
NSLog(#"File does not exists");
}
U forgot provide fileName for writing data:
DirPath=[self MyApplicationDocumentDirectory];
NSString *filePath = [DirPath stringByAppendingPathComponent:#"yourFileName"];
[receivedData writeToFile:filePath atomically:YES];
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.
Hi every One I am new to iPhone. I am retrieving data from remote server with using nsurlconnection and json parser..I am downloaded only one file from the server and i stored in documents path. But in my server url number of files are there like (images,audios,video,text files). How to download at a time when app lunch and save it in document directory. And also i want the same file name in documents as the file name in the server.
I have tried these way .
ViewController
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
NSMutableData *responseData;
NSArray *filesCount;
}
#property(nonatomic,retain)NSArray *filesCount;
#property(nonatomic,retain) NSMutableData *responseData;
#end
.m viewController
#import "ViewController.h"
#import "JSON/JSON.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize filesCount,responseData;
- (void)viewDidLoad
{
[super viewDidLoad];
responseData =[[NSMutableData data]retain];
NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://XXXXXXX/XXXXX/filesCount.php"]];
[[NSURLConnection alloc]initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[responseData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[responseData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"" message:#"DidFailWithError" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSLog(#"response string is %#",responseString);
NSError *error;
SBJSON *json = [[SBJSON new] autorelease];
filesCount = [json objectWithString:responseString error:&error];
[responseString release];
NSLog(#"filesCount is %#",filesCount);
if (filesCount==nil) {
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"" message:#"Json parsing failed" delegate:self cancelButtonTitle:#"ok" otherButtonTitles: nil];
[alert show];
}
else{
NSMutableString *text = [NSMutableString stringWithString:#"\n"];
for (int i = 0; i < [filesCount count]; i++)
[text appendFormat:#"%#\n", [filesCount objectAtIndex:i]];
NSLog(#"text is %s",[text UTF8String]);
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:text ]]];
NSData *addImageData = UIImagePNGRepresentation(img);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSRange lastComma= [text rangeOfString:#"/" options:NSBackwardsSearch];
NSString *requiredSubString = [text substringFromIndex:(lastComma.location+1)];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:requiredSubString];
[fileManager createFileAtPath:savedImagePath contents:addImageData attributes:nil];
NSLog(#"Saved Document dir %#",savedImagePath);
UIAlertView *alert1=[[UIAlertView alloc]initWithTitle:#"" message:#"files are downloaded" delegate:self cancelButtonTitle:#"ok" otherButtonTitles: nil];
[alert1 show];
}
}
Please help me What wrong i mad.
I'm sorry, I really can't read your question very well. From what I see though you might benefit from looking at AFNetworking (https://github.com/AFNetworking/AFNetworking). It simplifies the process of downloading, and is rock-solid.
Look here for a nice tutorial: http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_afnetworking/
I am fairly new at this and tried to solve this problem for quite some time now. I want to download a file from a url and save it to the document folder on the device. After that I want to load it to a Webview. The webview part seems to work if I copy a file manually but when I save the URL it shows only 5529 bytes saved with the correct file name?
Down the road I will need to tackle loading file from a secure web-server, hence the connection Authenticate methods.
#interface ViewController ()
#end
#implementation ViewController
#synthesize webView;
#synthesize webData;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(void)handleDocumentOpenURL:(NSURL *)url
{
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[webView setUserInteractionEnabled:YES];
[webView loadRequest:req];
}
-(void)loadFileFromDocumentFolder:(NSString *) filename
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *file = [documentsDirectory stringByAppendingPathComponent:filename];
NSURL *urlPdf = [NSURL fileURLWithPath: file];
[self handleDocumentOpenURL:urlPdf];
}
- (IBAction)btnSave:(id)sender
{
NSString *urlString = #"http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/UIWebView_Class.pdf";
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
if (urlConnection)
{
webData = [NSMutableData data];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error !" message:#"Error has occured, please verify internet connection" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
}
- (IBAction)btnLoad:(UIButton *)sender
{
[self loadFileFromDocumentFolder:#"test.pdf"];
}
#pragma mark - NSURLConnection Delegate Methods
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"did fail");
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"did receive data");
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"did receive response");
[webData setLength:0];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
BOOL isSuccessfull;
NSLog(#"did finish loading. Bytes Received: %d", [webData length]);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:#"test.pdf"];
isSuccessfull = [webData writeToFile:pdfPath atomically:YES];
}
#end
I am trying to get an NSURLConnection to work in my app. I have followed apple's code almost exactly but it doesn't seem to work. The NSURLConnection is inside of a method called, downloadSave. This method runs properly through the end, and my log indicates, "Connection Exists" - however nothing happens after that as if none of the delegate methods get called.
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString *tempString = [[NSString alloc]initWithFormat:#"http://www.myWebsite.com/%#.jpg",chartFileName];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:tempString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
mutableData = [[NSMutableData data] retain];
self.image = nil;
NSLog(#"connection exists");
} else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Connection Error" message:#"There was an error contacting the servers. Please try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
[activityIndicator stopAnimating];
}
[pool drain];
[pool release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"got to connection did receive response");
[mutableData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutableData appendData:data];
NSLog(#"got some data were at %i",mutableData.length);
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[connection release];
// receivedData is declared as a method instance elsewhere
self.mutableData = nil;
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[mutableData length]);
//more code follows to display the downloaded image
}
The only thing that appears in the log is: "Connection Exists"
I can only guess by your code that downloadSave in called in a separate thread as you have an NSAutoReleasePool (not saying thats what your doing but its likely). NSURLConnection can only respond to the delegate methods in the main thread when it is initialised in the main thread.
As NSURLConnection already is a threaded delegate call you shouldn't need to create it in thread. If you need to thread it for some reason you should be able to use
NSError *error;
NSURLResponse *response;
NSData *connectionData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
And that should return the data to the child thread.
I was previously downloading images for my app by using dataWithContentsOfURL to download a jpg then writeToFile to save it.
I recent;y started using an NSURLConnetion to do the same, but now I am getting the follwoing errors and a crash:
Corrupt JPEG data: 87 extraneous bytes
JPEG datastream contains no image
I know these images are not corrumpt, as the app was downloading them fine using the previous method. Here is my code:
-(void) downloadSave {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString *tempString = [[NSString alloc]initWithFormat:#"http://www.mysite.com/%#.jpg",chartFileName];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:tempString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
mutableData = [[NSMutableData data] retain];
self.image = nil;
NSLog(#"connection exists");
[NSURLConnection connectionWithRequest:theRequest delegate:self];
} else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Connection Error" message:#"There was an error contacting the chart servers. Please try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
[activityIndicator stopAnimating];
}
// NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
// NSUserDomainMask, YES);
// NSString *docsPath = [paths objectAtIndex:0];
// NSString *downloadPath = [[[NSString alloc]initWithFormat:#"http://www.mysite.com/%#.jpg",chartFileName]autorelease];
// downloadedChartData = nil;
[pool drain];
[pool release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
NSLog(#"got to connection did receive response");
[mutableData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere.
[mutableData appendData:data];
// NSLog(#"got some data, total: %i",mutableData.length);
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// release the connection, and the data object
// [connection release];
// receivedData is declared as a method instance elsewhere
// self.mutableData = nil;
// inform the user
//NSLog(#"Connection failed! Error - %# %#",
// [error localizedDescription],
// [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a method instance elsewhere
NSLog(#"Succeeded! Received %d bytes of data",[mutableData length]);
[connection release];
// release the connection, and the data object
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
self.image = nil;
NSString *savePath = [[[NSString alloc]initWithFormat:#"%#/%#.jpg",docsPath, chartFileName]autorelease];
[mutableData writeToFile:savePath atomically:YES];
self.mutableData = nil;
You are initializing and starting two NSURLConnections with the same delegate. As your delegate methods do not check which connection called them you are mixing up the bytes of two times your image in one NSMutableData instance.
// Creates, initializes and starts an instance of NSURLConnection
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
...
// Creates, initializes and starts another instance of NSURLConnection, with same request and delegate
[NSURLConnection connectionWithRequest:theRequest delegate:self];
Both connections message the same implementations on the same delegate instance, which means their data is written into the same NSMutableData in random order.
I would suggest to simply get rid of the line:
[NSURLConnection connectionWithRequest:theRequest delegate:self];
Another thing: why are you using an autorelease pool in downloadSave? If you call it from the main Thread you have only one NSURLRequest autoreleased in that pool. If you call it from an other Thread you have to take care, that the runloop of that thread is setup and running, or you wouldn't receive any delegate callbacks at all.