iOS: Get file's metadata

2019-06-22 07:20发布

I have an mp3 file on a server. I want to get this file's information like what's the size of this file, what's the artists name, what's the album name, when was the file created, when was it modified, etc. I want all this information.

Is it possible to get this information without actually downloading the whole file? Using NSURLConnection or otherwise?

EDIT:

The following code doesn't give me the required information, i.e. file created by, artist name, etc

    NSError *rerror = nil;
    NSURLResponse *response = nil;

    NSURL *url = [NSURL URLWithString:@"http://link.to.mp3"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"HEAD"];

    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&rerror];
    NSString *resultString = [[[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding] autorelease];

    NSLog(@"URL: %@", url);
    NSLog(@"Request: %@", request);
    NSLog(@"Result (NSData): %@", result);
    NSLog(@"Result (NSString): %@", resultString);
    NSLog(@"Response: %@", response);
    NSLog(@"Error: %@", rerror);

    if ([response isMemberOfClass:[NSHTTPURLResponse class]]) {
        NSLog(@"AllHeaderFields: %@", [((NSHTTPURLResponse *)response) allHeaderFields]);
    }

The "AllHeaderFields" is:

AllHeaderFields: {
    "Cache-Control" = "max-age=0";
    Connection = "keep-alive";
    "Content-Encoding" = gzip;
    "Content-Type" = "text/plain; charset=ascii";
    Date = "Fri, 17 Feb 2012 12:44:59 GMT";
    Etag = 19202n;
    Pragma = public;
    Server = dbws;
    "x-robots-tag" = "noindex,nofollow";
}

3条回答
仙女界的扛把子
2楼-- · 2019-06-22 07:51

It is quite possible to get the ID3 information embedded in an MP3 file (artist name, track title) without downloading the whole file or using low-level APIs. The functionality is part of the AVFoundation framework.

The class to look at is AVAsset and specifically it's network friendly subclass AVURLAsset. AVAsset has an NSArray property named commonMetadata. This commonMetadata property will contain instances of AVMetadataItem, assuming of course that the reference URL contains metadata. You will usually use the AVMetadataItem's commonKey property to reference the item. I find this method of iterating through an array checking commonKeys irritating so I create an NSDictionary using the commonKey property as the key and the value property as the object. Like so:

-(NSDictionary *)dictionaryOfMetadataFromAsset:(AVAsset *)asset{
    NSMutableDictionary *metaData = [[NSMutableDictionary alloc] init];
    for (AVMetadataItem *item in asset.commonMetadata) {
        if (item.value && item.commonKey){
            [metaData setObject:item.value forKey:item.commonKey];
        }
    }
    return [metaData copy];
}

With the addition of this simple method the AVAsset's metadata becomes quite easy to use. Here is an example of getting an MP3's metadata through a URL:

NSURL *mp3URL = [NSURL URLWithString:@"http://'AddressOfMP3File'"];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:mp3URL options:nil];
NSDictionary *metaDict = [self dictionaryOfMetadataFromAsset:asset];
NSLog(@"Available Metadata :%@",metaDict.allKeys);
NSLog(@"title:%@",[metaDict objectForKey:@"title"]);

I have found that this code seems to load just the first few seconds of your MP3 file. Also note that this code is synchronous; So use with caution. But AVURLAsset does have some async functionality described in the docs.

Once you have the AVAsset you can create a AVPlayerItem with it and feed that to an AVPlayer and play it, or not.

查看更多
对你真心纯属浪费
3楼-- · 2019-06-22 07:58

Yes and no. Things like the file size and modification date often come as part of the HEAD response. But not always: with a lot of dynamic URLs, you won't get all of the information.

As for the artist and album name, they're part of the MP3's ID3, which is contained inside the file, and so you won't be able to get them with a HEAD request. Since the ID3 tag is typically at the beginning of a file, you could try to grab just that part and then read the ID3 tag. But you won't be able to do it with NSURLConnection since it doesn't support just fetching part of a file, so you'll need to find a more low-level way of getting data by HTTP.

查看更多
啃猪蹄的小仙女
4楼-- · 2019-06-22 08:02

Yep, you're right on target with NSURLConnection.

I think you want to send a HEAD request for the resource you want information about and then check the information you receive in connection:didReceiveResponse: and connection:didReceiveData:

Edit

Admittedly I didn't read your question in its entirety. It won't be possible to get ID3 information, but you should be able to get size of file and maybe creation date etc.

This answer does give some good information about how to get the ID3 information. You'd need to set up a php page to examine the mp3 file server-side and return just that information you require instead of the entire mp3.

查看更多
登录 后发表回答