VICacheManager.m 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //
  2. // VICacheManager.m
  3. // VIMediaCacheDemo
  4. //
  5. // Created by Vito on 4/21/16.
  6. // Copyright © 2016 Vito. All rights reserved.
  7. //
  8. #import "VICacheManager.h"
  9. #import "VIMediaDownloader.h"
  10. #import "NSString+VIMD5.h"
  11. NSString *VICacheManagerDidUpdateCacheNotification = @"VICacheManagerDidUpdateCacheNotification";
  12. NSString *VICacheManagerDidFinishCacheNotification = @"VICacheManagerDidFinishCacheNotification";
  13. NSString *VICacheConfigurationKey = @"VICacheConfigurationKey";
  14. NSString *VICacheFinishedErrorKey = @"VICacheFinishedErrorKey";
  15. static NSString *kMCMediaCacheDirectory;
  16. static NSTimeInterval kMCMediaCacheNotifyInterval;
  17. static NSString *(^kMCFileNameRules)(NSURL *url);
  18. @implementation VICacheManager
  19. + (void)load {
  20. static dispatch_once_t onceToken;
  21. dispatch_once(&onceToken, ^{
  22. [self setCacheDirectory:[NSTemporaryDirectory() stringByAppendingPathComponent:@"vimedia"]];
  23. [self setCacheUpdateNotifyInterval:0.1];
  24. });
  25. }
  26. + (void)setCacheDirectory:(NSString *)cacheDirectory {
  27. kMCMediaCacheDirectory = cacheDirectory;
  28. }
  29. + (NSString *)cacheDirectory {
  30. return kMCMediaCacheDirectory;
  31. }
  32. + (void)setCacheUpdateNotifyInterval:(NSTimeInterval)interval {
  33. kMCMediaCacheNotifyInterval = interval;
  34. }
  35. + (NSTimeInterval)cacheUpdateNotifyInterval {
  36. return kMCMediaCacheNotifyInterval;
  37. }
  38. + (void)setFileNameRules:(NSString *(^)(NSURL *url))rules {
  39. kMCFileNameRules = rules;
  40. }
  41. + (NSString *)cachedFilePathForURL:(NSURL *)url {
  42. NSString *pathComponent = nil;
  43. if (kMCFileNameRules) {
  44. pathComponent = kMCFileNameRules(url);
  45. } else {
  46. pathComponent = [url.absoluteString vi_md5];
  47. pathComponent = [pathComponent stringByAppendingPathExtension:url.pathExtension];
  48. }
  49. return [[self cacheDirectory] stringByAppendingPathComponent:pathComponent];
  50. }
  51. + (VICacheConfiguration *)cacheConfigurationForURL:(NSURL *)url {
  52. NSString *filePath = [self cachedFilePathForURL:url];
  53. VICacheConfiguration *configuration = [VICacheConfiguration configurationWithFilePath:filePath];
  54. return configuration;
  55. }
  56. + (unsigned long long)calculateCachedSizeWithError:(NSError **)error {
  57. NSFileManager *fileManager = [NSFileManager defaultManager];
  58. NSString *cacheDirectory = [self cacheDirectory];
  59. NSArray *files = [fileManager contentsOfDirectoryAtPath:cacheDirectory error:error];
  60. unsigned long long size = 0;
  61. if (files) {
  62. for (NSString *path in files) {
  63. NSString *filePath = [cacheDirectory stringByAppendingPathComponent:path];
  64. NSDictionary<NSFileAttributeKey, id> *attribute = [fileManager attributesOfItemAtPath:filePath error:error];
  65. if (!attribute) {
  66. size = -1;
  67. break;
  68. }
  69. size += [attribute fileSize];
  70. }
  71. }
  72. return size;
  73. }
  74. + (void)cleanAllCacheWithError:(NSError **)error {
  75. // Find downloaing file
  76. NSMutableSet *downloadingFiles = [NSMutableSet set];
  77. [[[VIMediaDownloaderStatus shared] urls] enumerateObjectsUsingBlock:^(NSURL * _Nonnull obj, BOOL * _Nonnull stop) {
  78. NSString *file = [self cachedFilePathForURL:obj];
  79. [downloadingFiles addObject:file];
  80. NSString *configurationPath = [VICacheConfiguration configurationFilePathForFilePath:file];
  81. [downloadingFiles addObject:configurationPath];
  82. }];
  83. // Remove files
  84. NSFileManager *fileManager = [NSFileManager defaultManager];
  85. NSString *cacheDirectory = [self cacheDirectory];
  86. NSArray *files = [fileManager contentsOfDirectoryAtPath:cacheDirectory error:error];
  87. if (files) {
  88. for (NSString *path in files) {
  89. NSString *filePath = [cacheDirectory stringByAppendingPathComponent:path];
  90. if ([downloadingFiles containsObject:filePath]) {
  91. continue;
  92. }
  93. if (![fileManager removeItemAtPath:filePath error:error]) {
  94. break;
  95. }
  96. }
  97. }
  98. }
  99. + (void)cleanCacheForURL:(NSURL *)url error:(NSError **)error {
  100. if ([[VIMediaDownloaderStatus shared] containsURL:url]) {
  101. NSString *description = [NSString stringWithFormat:NSLocalizedString(@"Clean cache for url `%@` can't be done, because it's downloading", nil), url];
  102. if (error) {
  103. *error = [NSError errorWithDomain:@"com.mediadownload" code:2 userInfo:@{NSLocalizedDescriptionKey: description}];
  104. }
  105. return;
  106. }
  107. NSFileManager *fileManager = [NSFileManager defaultManager];
  108. NSString *filePath = [self cachedFilePathForURL:url];
  109. if ([fileManager fileExistsAtPath:filePath]) {
  110. if (![fileManager removeItemAtPath:filePath error:error]) {
  111. return;
  112. }
  113. }
  114. NSString *configurationPath = [VICacheConfiguration configurationFilePathForFilePath:filePath];
  115. if ([fileManager fileExistsAtPath:configurationPath]) {
  116. if (![fileManager removeItemAtPath:configurationPath error:error]) {
  117. return;
  118. }
  119. }
  120. }
  121. + (BOOL)addCacheFile:(NSString *)filePath forURL:(NSURL *)url error:(NSError **)error {
  122. NSFileManager *fileManager = [NSFileManager defaultManager];
  123. NSString *cachePath = [VICacheManager cachedFilePathForURL:url];
  124. NSString *cacheFolder = [cachePath stringByDeletingLastPathComponent];
  125. if (![fileManager fileExistsAtPath:cacheFolder]) {
  126. if (![fileManager createDirectoryAtPath:cacheFolder
  127. withIntermediateDirectories:YES
  128. attributes:nil
  129. error:error]) {
  130. return NO;
  131. }
  132. }
  133. if (![fileManager copyItemAtPath:filePath toPath:cachePath error:error]) {
  134. return NO;
  135. }
  136. if (![VICacheConfiguration createAndSaveDownloadedConfigurationForURL:url error:error]) {
  137. [fileManager removeItemAtPath:cachePath error:nil]; // if remove failed, there is nothing we can do.
  138. return NO;
  139. }
  140. return YES;
  141. }
  142. @end