How to query the last modification date of a file via HTTP on the iPhone using NSHTTPURLResponse?
Asked Answered
H

2

6

In my iPhone application I need to query the last modification date of an internet .m4a file via HTTP, but I DON'T want to downloading it.

I'm reading Apple's documentation about NSURLRequest and NSHTTPURLResponse, but it seems to be all related to downloading the file and not querying it first. Maybe I'm wrong.

How can I know the last modification date of a .m4a file, via HTTP, WITHOUT downloading it?

Thanks!

Haiphong answered 1/6, 2012 at 19:33 Comment(1)
I really dont think that its possible to query this sort of data without downloading the file, i dont think is doable in iphone or any other sdk.Sinistrodextral
C
9

This answer assumes your server supports it, but what you do is send a "HEAD" request to the file URL and you get back just the file headers. You can then inspect the header called "Last-Modified" which normally has the date format @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'".

Here's some code:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"HEAD"];
NSHTTPURLResponse *response;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
if ([response respondsToSelector:@selector(allHeaderFields)]) 
{
  NSDictionary *dictionary = [response allHeaderFields];
  NSString *lastUpdated = [dictionary valueForKey:@"Last-Modified"];
  NSDate *lastUpdatedServer = [fileDateFormatter dateFromString:lastUpdated];

  if (([localCreateDate earlierDate:lastUpdatedServer] == localCreateDate) && lastUpdatedServer) 
  {
    NSLog(@"local file is outdated: %@ ", localPath);
    isLatest = NO;
  } else {
    NSLog(@"local file is current: %@ ", localPath);
  }

} else {
  NSLog(@"Failed to get server response headers");
}

Of course, you probably want this to be done asynchronously in the background, but this code should point you in the right direction.

Best Regards.

Cryptic answered 1/6, 2012 at 19:56 Comment(3)
Sure! It helped me a lot and now I'll work to make it asynchronously!Haiphong
Of course if the server doesn't support HEAD, you can simply cancel the connection as soon as you've received the responseDominican
Thanks for the hint, but in my case the server does support HEAD.Haiphong
P
4

The method below performs a HEAD request to only fetch the header with a Last-Modified field and converts it to NSDate object.

- (NSDate *)lastModificationDateOfFileAtURL:(NSURL *)url
{
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    // Set the HTTP method to HEAD to only get the header.
    request.HTTPMethod = @"HEAD";
    NSHTTPURLResponse *response = nil;
    NSError *error = nil;

    [NSURLConnection sendSynchronousRequest:request
                          returningResponse:&response
                                      error:&error];

    if (error)
    {
        NSLog(@"Error: %@", error.localizedDescription);
        return nil;
    }
    else if([response respondsToSelector:@selector(allHeaderFields)])
    {
        NSDictionary *headerFields = [response allHeaderFields];
        NSString *lastModification = [headerFields objectForKey:@"Last-Modified"];

        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss zzz"];

        return [formatter dateFromString:lastModification];
    }

    return nil;
}

You should run this method asynchronously in the background so the main thread is not blocked waiting for the response. This can be easily done using couple of lines of GCD.

The code below performs a call to fetch the last modification date in a background thread, and call a completion block on the main thread when the date is retrieved.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
    // Perform a call on the background thread.
    NSURL *url = [NSURL URLWithString:@"yourFileURL"];

    NSDate *lastModifDate = [self lastModificationDateOfFileAtURL:url];

    dispatch_async(dispatch_get_main_queue(), ^
    {
        // Do stuff with lastModifDate on the main thread.
    });
});

I wrote an article about this here:

Getting last modification date of a file on the server using Objective-C.

Palomo answered 20/4, 2014 at 12:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.