-
Notifications
You must be signed in to change notification settings - Fork 4
/
Downloader.m
114 lines (77 loc) · 3.7 KB
/
Downloader.m
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
#import "Downloader.h"
@implementation DownloadParams
@end
@interface Downloader()
@property (copy) DownloadParams* params;
@property (retain) NSURLConnection* connection;
@property (retain) NSNumber* statusCode;
@property (retain) NSNumber* contentLength;
@property (retain) NSNumber* bytesWritten;
@property (retain) NSFileHandle* fileHandle;
@end
@implementation Downloader
- (void)downloadFile:(DownloadParams*)params
{
_params = params;
_bytesWritten = 0;
NSURL* url = [NSURL URLWithString:_params.fromUrl];
NSMutableURLRequest* downloadRequest = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30];
_connection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self startImmediately:NO];
[_connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[_connection start];
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
[_fileHandle closeFile];
NSString *tempPath = [_params.toFile stringByAppendingPathExtension:@"tmp"];
NSError *err = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:tempPath isDirectory:false]) {
[[NSFileManager defaultManager] removeItemAtPath:tempPath error:&err];
}
return _params.errorCallback(error);
}
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
NSString *tempPath = [_params.toFile stringByAppendingPathExtension:@"tmp"];
[[NSFileManager defaultManager] createFileAtPath:tempPath contents:nil attributes:nil];
[[NSURL fileURLWithPath:tempPath] setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
_fileHandle = [NSFileHandle fileHandleForWritingAtPath:tempPath];
if (!_fileHandle) {
NSError* error = [NSError errorWithDomain:@"Downloader" code:NSURLErrorFileDoesNotExist userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"Failed to create target file at path: %@", tempPath]}];
if (_params.errorCallback) {
return _params.errorCallback(error);
}
}
NSHTTPURLResponse* httpUrlResponse = (NSHTTPURLResponse*)response;
_statusCode = [NSNumber numberWithLong:httpUrlResponse.statusCode];
_contentLength = [NSNumber numberWithLongLong: httpUrlResponse.expectedContentLength];
return _params.beginCallback(_statusCode, _contentLength, httpUrlResponse.allHeaderFields);
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
if ([_statusCode isEqualToNumber:[NSNumber numberWithInt:200]]) {
[_fileHandle writeData:data];
_bytesWritten = [NSNumber numberWithUnsignedInteger:[_bytesWritten unsignedIntegerValue] + data.length];
return _params.progressCallback(_contentLength, _bytesWritten);
}
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
[_fileHandle closeFile];
NSString *tempPath = [_params.toFile stringByAppendingPathExtension:@"tmp"];
NSError *error = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:_params.toFile isDirectory:false]) {
[[NSFileManager defaultManager] removeItemAtPath:_params.toFile error:&error];
}
[[NSFileManager defaultManager] moveItemAtPath:tempPath toPath:_params.toFile error:&error];
[[NSURL fileURLWithPath:_params.toFile] setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:_params.toFile error:&error];
return _params.callback(_statusCode, [fileAttributes valueForKey:@"NSFileSize"]);
}
- (void)stopDownload
{
[_connection cancel];
}
@end