IOS - Download file only if modified (NSURL & NSData)
I am downloading a bunch of image files from the server and I want to make sure they only download if they are newer. This method currently loads images just fine. However, I don't want to waste time or energy re-loading images every time the user logs into the app. Instead, I only want to download any files that A) Don't exist B) Newer on the server than on the device
This is how I load the images: * The image url is stored in Core Data with the video it is linked to. The url is generated using a simple transform method that I am building (generateThumbnailURL)
-(void)saveThumbnails{
NSManagedObjectContext *context = [self managedObjectContextThumbnails];
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Videos" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
NSLog(@"Videos: %i",fetchedObjects.count);
if (fetchedObjects.count!=0) {
for(Videos *currentVideo in fetchedObjects){
// Get an image from the URL below
NSURL *thumbnailURL = [self generateThumbnailURL:[currentVideo.videoID intValue]];
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:thumbnailURL]];
// Let save the file into Document folder.
// You can also change this to your desktop for testing. (e.g. /Users/kiichi/Desktop/)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);//Find Application Document Directory
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"DownloadedThumbnails"];
// NSString *dataPath = @"/Users/macminidemo/Desktop/gt";//DEBUG SAVING IMAGE BY SAVING TO DESKTOP FOLDER
//Check if Sub-directory exists, if not, try to create it
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]){
NSError* error;
if([[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]){
NSLog(@"New Folder Created!");
}
else
{
NSLog(@"[%@] ERROR: attempting to write create new directory", [self class]);
NSAssert( FALSE, @"Failed to create directory maybe out of disk space?");
}
}
NSArray *splitFilename = [[self generateThumbnailFilename:[currentVideo.videoID intValue]] componentsSeparatedByString:@"."];//Break Filename Extension Off (not always PNGs)
NSString *subString = [splitFilename objectAtIndex:0];
NSString *formattedFilename = [NSString stringWithFormat:@"%@~ipad.png",subString];
NSString *localFilePath = [dataPath stringByAppendingPathComponent:formattedFilename];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
[imageData writeToFile:localFilePath atomically:YES];
NSLog(@"Image: %@ Saved!",formattedFilename);
}
}
}
source to share
As a result, I used this method to detect the changed date in the file: * Found on HERE
-(bool)isThumbnailModified:(NSURL *)thumbnailURL forFile:(NSString *)thumbnailFilePath{
// create a HTTP request to get the file information from the web server
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:thumbnailURL];
[request setHTTPMethod:@"HEAD"];
NSHTTPURLResponse* response;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
// get the last modified info from the HTTP header
NSString* httpLastModified = nil;
if ([response respondsToSelector:@selector(allHeaderFields)])
{
httpLastModified = [[response allHeaderFields]
objectForKey:@"Last-Modified"];
}
// setup a date formatter to query the server file modified date
// don't ask me about this part of the code ... it works, that all I know :)
NSDateFormatter* df = [[NSDateFormatter alloc] init];
df.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
df.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
// get the file attributes to retrieve the local file modified date
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary* fileAttributes = [fileManager attributesOfItemAtPath:thumbnailFilePath error:nil];
// test if the server file date is later than the local file date
NSDate* serverFileDate = [df dateFromString:httpLastModified];
NSDate* localFileDate = [fileAttributes fileModificationDate];
NSLog(@"Local File Date: %@ Server File Date: %@",localFileDate,serverFileDate);
//If file doesn't exist, download it
if(localFileDate==nil){
return YES;
}
return ([localFileDate laterDate:serverFileDate] == serverFileDate);
}
source to share
If your server supports HTTP caching, you can indicate that you want to store cached content with NSURLRequestReloadRevalidatingCacheData
:
NSURLRequest* request = [NSURLRequest requestWithURL:thumbnailURL cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:20];
NSURLResponse* response;
NSError* error;
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
UIImage* image = [UIImage imageWithData:data];
Read the NSURLRequest documentation for details .
source to share