I am using the following code to download images. Can someone confirm the images are being downloaded asynchronously as they would appear to be? Normally, they download rapidly but every now and then the UI freezes for a minute while data comes through so something would appear to be awry:
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1
NSString *picURL = [NSString stringWithFormat:#"http://~/pics/%#",picname];
NSURL *urlPicUrl = [NSURL URLWithString:picURL];
dispatch_async(kBgQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:picURL]];
if (imgData) {
UIImage *imageCache = [[UIImage alloc] init];
imageCache = [UIImage imageWithData:imgData];
if (imageCache) {
[self saveImage:imageCache asPicName:picname];
dispatch_async(dispatch_get_main_queue(), ^{
});
}
}
});
EDIT:
Here is code to save image.
- (void)saveImage: (UIImage*)image asPicName: (NSString*)picname
{
if (image != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
[NSString stringWithString: picname] ];
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:path atomically:YES];
}
}
Related
I am getting responseObject like this
responseObject =
{
"img": "images/ProfileImage/defaultImg.jpg",
}
I have to store this image in app folder. Is there any way to do this.
The path is incomplete
You need to append base URL before "images/ProfileImage/defaultImg.jpg"
Then
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *urlToDownload = BaseURL + "images/ProfileImage/defaultImg.jpg";
NSURL *url = [NSURL URLWithString:urlToDownload];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if (urlData)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"defaultImg.png"];
//saving is done on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:filePath atomically:YES];
NSLog(#"File Saved !");
});
}
});
Here is the code for downloading image and store into a local i.e "Document" directory in iOS app folder
In below code urlString is the url of image.
dispatch_queue_t downloadThumbNail = dispatch_queue_create("com.download.thumbnail", NULL);
dispatch_async(downloadThumbNail, ^
{
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
UIImage *imageThumb = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(),
^{
NSString *str = #“filename.png”;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:str];
NSData *pngData = UIImagePNGRepresentation(imageThumb);
[pngData writeToFile:filePath atomically:YES];
});
});
Enjoy codeing.
My question is what format the image is saved, if is dat or jpg. This is the code that i used:
NSString * urlImage = .....;
NSString * _folderPath = .....;
NSString * imageName = [[urlImage componentsSeparatedByString:#"/"] lastObject];
NSString * jpegPath = [NSString stringWithFormat:#"%#%#",_folderPath,imageName];
if (![[NSFileManager defaultManager] fileExistsAtPath:jpegPath])
{
NSURL *url = [NSURL URLWithString:urlImage];
//Download image
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:url]];
//Save image
NSData *data = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];//1.0f = 100% quality
[data writeToFile:jpegPath atomically:YES];
}
Following is piece of code for save .jpg image
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docs = [paths objectAtIndex:0];
NSString* path = [docs stringByAppendingFormat:#"/image1.jpg"];
NSData* imageData = [NSData dataWithData:UIImageJPEGRepresentation(imageView.image, 80)];
NSError *writeError = nil;
[imageData writeToFile:path options:NSDataWritingAtomic error:&writeError];
You should use
stringByAppendingPathComponent method to create or get exact valid path
Use this way:
NSString * jpegPath = [_folderPath stringByAppendingPathComponent:imageName];// [NSString stringWithFormat:#"%#%#",_folderPath,imageName];
I've created folder called "Image store" using the following code. my requirment is i want to save images to the folder "Image store" on api success and the images should be saved in application itself not in database or photo album.I want to know the mechanism by which i can store images in application
-(void) createFolder {
UIImage *image = [[UIImage alloc]init];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/ImageStore"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
else
{
}
}
//Make a method that has url (fileName) Param
NSArray *documentsDirectory =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:url];
NSFileManager *fileManager =[NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:textPath])
{
return YES;
}
else
{
return NO;
}
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage
imageNamed:#""]];//Placeholder image
if ([url isKindOfClass:[NSString class]])
{
imgView.image = [UIImage imageNamed:[url absoluteString]];
imgView.contentMode = UIViewContentModeScaleAspectFit;
}
else if ([fileManager fileExistsAtPath:url])
{
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:url];
NSError *error = nil;
NSData *fileData = [NSData dataWithContentsOfFile:textPath options:NSDataReadingMappedIfSafe error:&error];
if (error != nil)
{
DLog(#"There was an error: %#", [error description]);
imgView.image=nil;
}
else
{
imgView.image= [UIImage imageWithData:fileData]
}
}
else
{ UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
CGPoint center = imgView.center;
// center.x = imgView.bounds.size.width / 2;
spinner.center = center;
[spinner startAnimating];
[imgView addSubview:spinner];
dispatch_queue_t downloadQueue = dispatch_queue_create("iamge downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
[spinner removeFromSuperview];
UIImage *image = [UIImage imageWithData:imgData];
NSError *error = nil;
[imgData writeToFile:url options:NSDataWritingFileProtectionNone error:&error];
if (error != nil)
{
}
else
{
}
imgView.image = image;
});
});
}
Thats UIImageView loading an image if it doesnot exist in document then it Save it , An Activity indicator is added to show image is loading to save,
u can do something like this
u can run a loop for images like this
//at this point u can get image data
for(int k = 0 ; k < imageCount; k++)
{
[self savePic:[NSString stringWithFormat:#"picName%d",k] withData:imageData];//hear data for each pic u can send
}
- (void)savePic:(NSString *)picName withData:(NSData *)imageData
{
if(imageData != nil)
{
NSString *path = [NSString stringWithFormat:#"/ImageStore/%#.png",pincName];
NSString *Dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngPath = [NSString stringWithFormat:#"%#%#",Dir,path]; //path means ur destination contain's this format -> "/foldername/picname" pickname must be unique
if(![[NSFileManager defaultManager] fileExistsAtPath:[pngPath stringByDeletingLastPathComponent]])
{
NSError *error;
[[NSFileManager defaultManager] createDirectoryAtPath:[pngPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:&error];
if(error)
{
NSLog(#"error in creating dir");
}
}
[imageData writeToFile:pngPath atomically:YES];
}
}
after successful download and saving u can retrieve images like below
- (UIImage *)checkForImageIn:(NSString *)InDestination
{
NSString *Dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngPath = [NSString stringWithFormat:#"%#%#",Dir,InDestination];//hear "InDestination" format is like this "/yourFolderName/imagename" as i said imagename must be unique .. :)
UIImage *image = [UIImage imageWithContentsOfFile:pngPath];
if(image)
{
return image;
}
else
return nil;
}
link to find path
see this link to find the path ..
aganin do same this run loop like below
NSMutableArray *imagesArray = [[NSMutableArray alloc]init];
for(int k = 0 ; k < imageCount; k++)
{
UIImage *image = [self checkForImageIn:[NSString stringWithFormat: #"/yourFolderName/ImageName%d",k]];//get the image
[imagesArray addObject:image];//store to use it somewhere ..
}
Write this code after creating directory
NSString *path= [documentsDirectory stringByAppendingPathComponent:#"/ImageStore"];
UIImage *rainyImage =[UImage imageNamed:#"rainy.jpg"];
NSData *Data= UIImageJPEGRepresentation(rainyImage,0.0);
[data writeToFile:path atomically:YES]
The document directory is found like this:
// Let's save the file into Document folder.
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
// If you go to the folder below, you will find those pictures
NSLog(#"%#",docDir);
NSLog(#"saving png");
NSString *pngFilePath = [NSString stringWithFormat:#"%#/test.png",docDir];
Thats just a sample of the code provided which tells you where the correct path is to save in your ipone device.
Check the below blog post,it's step by step guide with source code .
Download an Image and Save it as PNG or JPEG in iPhone SDK
Building an app which gives the users the option to change the backgroud of the app.
Currently using this code to save images from the picker.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
customImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *data = UIImagePNGRepresentation(customImage);
NSString *fetchCustomImage = #"userCustomImage.png";
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path objectAtIndex:0];
NSString *fullPathToFile = [documentDirectory stringByAppendingPathComponent:fetchCustomImage];
[data writeToFile:fullPathToFile atomically:YES];
[self dismissViewControllerAnimated:YES completion:NULL];
[self performSelector:#selector(fetchCustomBackground)]
}
Then calls a void to display the image
- (void)fetchCustomBackground
{
//Fetch Background Image
NSString *fetchUserImage = #"userCustomImage.png";
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path objectAtIndex:0];
NSString *fullPath = [documentDirectory stringByAppendingPathComponent:fetchUserImage];
NSData *data = [NSData dataWithContentsOfFile:fullPath];
[background setImage:[UIImage imageWithData:data]];
}
In the viewDidLoad
[self performSelector:#selector(fetchCustomBackground)];
At the moment the app is very slow I guess because every time the view loads it has to fetch the image, is there a way to save it so you don't have to call it every time the view loads?
Try to update your function like this.
- (void)fetchCustomBackground
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
__block NSData *data;
dispatch_sync(concurrentQueue, ^{
//Fetch Background Image
NSString *fetchUserImage = #"userCustomImage.png";
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path objectAtIndex:0];
NSString *fullPath = [documentDirectory stringByAppendingPathComponent:fetchUserImage];
data = [NSData dataWithContentsOfFile:fullPath];
});
dispatch_sync(dispatch_get_main_queue(), ^{
[background setImage:[UIImage imageWithData:data]];
}); });
}
I see no problem with loading a a single picture from Documents. But for sure, if you are loading a large picture and doing simultanely some UI updates, it can be problem. You have to free main thread using Grand Central Dispatch.
I create one application that download file from url with any size.I have one button and one progress view in my page . I want when click on button downloaded file and show me download's status in progress view.
I can download any file with this code but I dont know how to use progress view with this code:
- (IBAction)Download:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Downloading Started");
NSString *urlToDownload = #"http://192.168.1.100/emma/Adele%20-%20Someone%20Like%20You%20(MTV%20Video%20Music%20Awards%202011)%20HD%20Live.mkv";
NSURL *url = [NSURL URLWithString:urlToDownload];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"filename.mkv"];
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:filePath atomically:YES];
NSLog(#"File Saved !");
});
x = 1;
NSLog(#"x : %d",x);
}
});
}
please guide me about it.
define NSTimer *timer in your .h file and set your ProgressView in your .xib
- (IBAction)Download:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Downloading Started");
NSString *urlToDownload = #"http://192.168.1.100/emma/Adele%20-%20Someone%20Like%20You%20(MTV%20Video%20Music%20Awards%202011)%20HD%20Live.mkv";
NSURL *url = [NSURL URLWithString:urlToDownload];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"filename.mkv"];
timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:#selector(updateProgressView) userInfo:nil repeats:YES];
[timer fire];
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:filePath atomically:YES];
NSLog(#"File Saved !");
});
x = 1;
NSLog(#"x : %d",x);
}
});
}
and add this method
- (void) updateProgressView{
NSString *urlToDownload = #"http://192.168.1.100/emma/Adele%20-%20Someone%20Like%20You%20(MTV%20Video%20Music%20Awards%202011)%20HD%20Live.mkv";
NSURL *url = [NSURL URLWithString:urlToDownload];
NSData *urlData = [NSData dataWithContentsOfURL:url];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"filename.mkv"];
NSData *writtenData = [NSData dataWithContentsOfFile:filePath];
float progress = [writtenData length]/(float)[urlData length];
[progressView setProgress:progress];
if (progress == 1.0){
[timer invalidate];
}
}