// // VICacheManager.m // VIMediaCacheDemo // // Created by Vito on 4/21/16. // Copyright © 2016 Vito. All rights reserved. // #import "VICacheManager.h" #import "VIMediaDownloader.h" #import "NSString+VIMD5.h" NSString *VICacheManagerDidUpdateCacheNotification = @"VICacheManagerDidUpdateCacheNotification"; NSString *VICacheManagerDidFinishCacheNotification = @"VICacheManagerDidFinishCacheNotification"; NSString *VICacheConfigurationKey = @"VICacheConfigurationKey"; NSString *VICacheFinishedErrorKey = @"VICacheFinishedErrorKey"; static NSString *kMCMediaCacheDirectory; static NSTimeInterval kMCMediaCacheNotifyInterval; static NSString *(^kMCFileNameRules)(NSURL *url); @implementation VICacheManager + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self setCacheDirectory:[NSTemporaryDirectory() stringByAppendingPathComponent:@"vimedia"]]; [self setCacheUpdateNotifyInterval:0.1]; }); } + (void)setCacheDirectory:(NSString *)cacheDirectory { kMCMediaCacheDirectory = cacheDirectory; } + (NSString *)cacheDirectory { return kMCMediaCacheDirectory; } + (void)setCacheUpdateNotifyInterval:(NSTimeInterval)interval { kMCMediaCacheNotifyInterval = interval; } + (NSTimeInterval)cacheUpdateNotifyInterval { return kMCMediaCacheNotifyInterval; } + (void)setFileNameRules:(NSString *(^)(NSURL *url))rules { kMCFileNameRules = rules; } + (NSString *)cachedFilePathForURL:(NSURL *)url { NSString *pathComponent = nil; if (kMCFileNameRules) { pathComponent = kMCFileNameRules(url); } else { pathComponent = [url.absoluteString vi_md5]; pathComponent = [pathComponent stringByAppendingPathExtension:url.pathExtension]; } return [[self cacheDirectory] stringByAppendingPathComponent:pathComponent]; } + (VICacheConfiguration *)cacheConfigurationForURL:(NSURL *)url { NSString *filePath = [self cachedFilePathForURL:url]; VICacheConfiguration *configuration = [VICacheConfiguration configurationWithFilePath:filePath]; return configuration; } + (unsigned long long)calculateCachedSizeWithError:(NSError **)error { NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *cacheDirectory = [self cacheDirectory]; NSArray *files = [fileManager contentsOfDirectoryAtPath:cacheDirectory error:error]; unsigned long long size = 0; if (files) { for (NSString *path in files) { NSString *filePath = [cacheDirectory stringByAppendingPathComponent:path]; NSDictionary *attribute = [fileManager attributesOfItemAtPath:filePath error:error]; if (!attribute) { size = -1; break; } size += [attribute fileSize]; } } return size; } + (void)cleanAllCacheWithError:(NSError **)error { // Find downloaing file NSMutableSet *downloadingFiles = [NSMutableSet set]; [[[VIMediaDownloaderStatus shared] urls] enumerateObjectsUsingBlock:^(NSURL * _Nonnull obj, BOOL * _Nonnull stop) { NSString *file = [self cachedFilePathForURL:obj]; [downloadingFiles addObject:file]; NSString *configurationPath = [VICacheConfiguration configurationFilePathForFilePath:file]; [downloadingFiles addObject:configurationPath]; }]; // Remove files NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *cacheDirectory = [self cacheDirectory]; NSArray *files = [fileManager contentsOfDirectoryAtPath:cacheDirectory error:error]; if (files) { for (NSString *path in files) { NSString *filePath = [cacheDirectory stringByAppendingPathComponent:path]; if ([downloadingFiles containsObject:filePath]) { continue; } if (![fileManager removeItemAtPath:filePath error:error]) { break; } } } } + (void)cleanCacheForURL:(NSURL *)url error:(NSError **)error { if ([[VIMediaDownloaderStatus shared] containsURL:url]) { NSString *description = [NSString stringWithFormat:NSLocalizedString(@"Clean cache for url `%@` can't be done, because it's downloading", nil), url]; if (error) { *error = [NSError errorWithDomain:@"com.mediadownload" code:2 userInfo:@{NSLocalizedDescriptionKey: description}]; } return; } NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *filePath = [self cachedFilePathForURL:url]; if ([fileManager fileExistsAtPath:filePath]) { if (![fileManager removeItemAtPath:filePath error:error]) { return; } } NSString *configurationPath = [VICacheConfiguration configurationFilePathForFilePath:filePath]; if ([fileManager fileExistsAtPath:configurationPath]) { if (![fileManager removeItemAtPath:configurationPath error:error]) { return; } } } + (BOOL)addCacheFile:(NSString *)filePath forURL:(NSURL *)url error:(NSError **)error { NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *cachePath = [VICacheManager cachedFilePathForURL:url]; NSString *cacheFolder = [cachePath stringByDeletingLastPathComponent]; if (![fileManager fileExistsAtPath:cacheFolder]) { if (![fileManager createDirectoryAtPath:cacheFolder withIntermediateDirectories:YES attributes:nil error:error]) { return NO; } } if (![fileManager copyItemAtPath:filePath toPath:cachePath error:error]) { return NO; } if (![VICacheConfiguration createAndSaveDownloadedConfigurationForURL:url error:error]) { [fileManager removeItemAtPath:cachePath error:nil]; // if remove failed, there is nothing we can do. return NO; } return YES; } @end