1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//
// VICacheManager.m
// VIMediaCacheDemo
//
// Created by Vito on 4/21/16.
// Copyright © 2016 Vito. All rights reserved.
//
#import "VICacheManager.h"
#import "VIMediaDownloader.h"
NSString *VICacheManagerDidUpdateCacheNotification = @"VICacheManagerDidUpdateCacheNotification";
NSString *VICacheManagerDidFinishCacheNotification = @"VICacheManagerDidFinishCacheNotification";
NSString *VICacheConfigurationKey = @"VICacheConfigurationKey";
NSString *VICacheFinishedErrorKey = @"VICacheFinishedErrorKey";
static NSString *kMCMediaCacheDirectory;
static NSTimeInterval kMCMediaCacheNotifyInterval;
@implementation VICacheManager
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self setCacheDirectory:[kPathCaches stringByAppendingPathComponent:@"Video"]];
[self setCacheUpdateNotifyInterval:0.1];
});
}
+ (void)setCacheDirectory:(NSString *)cacheDirectory {
kMCMediaCacheDirectory = cacheDirectory;
}
+ (NSString *)cacheDirectory {
return kMCMediaCacheDirectory;
}
+ (void)setCacheUpdateNotifyInterval:(NSTimeInterval)interval {
kMCMediaCacheNotifyInterval = interval;
}
+ (NSTimeInterval)cacheUpdateNotifyInterval {
return kMCMediaCacheNotifyInterval;
}
+ (NSString *)cachedFilePathForURL:(NSURL *)url {
return [[self cacheDirectory] stringByAppendingPathComponent:[url lastPathComponent]];
}
+ (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<NSFileAttributeKey, id> *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];
*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