This repository has been archived by the owner on Dec 7, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DownloadFileOperation.m
190 lines (159 loc) · 5.24 KB
/
DownloadFileOperation.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
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//
// DownloadFileOperation.m
// PikchaTV
//
// Created by Tuan-Ngoc Le on 10/27/12.
//
//
#import "DownloadFileOperation.h"
@implementation DownloadFileOperation
@synthesize error = error_, connectionURL=connectionURL_, userInfo=userInfo_, fileSize=fileSize_, receivedSize=receivedSize_, filePath, delegate;
- (void)dealloc
{
self.delegate = nil;
if(connection_) {
[connection_ cancel];
connection_ = nil;
[stream close];
stream = nil;
}
connectionURL_ = nil;
error_ = nil;
self.filePath = nil;
}
-(id)initWithUrl:(NSURL *)aUrl saveToFilePath:(NSString *)aFilePath {
if ((self = [super init])) {
connectionURL_ = [aUrl copy];
self.filePath = aFilePath;
stream = [[NSOutputStream alloc] initToFileAtPath:aFilePath append:NO];
}
return self;
}
- (void)done:(BOOL)isSuccess
{
if( connection_ ) {
[connection_ cancel];
connection_ = nil;
[stream close];
stream = nil;
fileSize_ = 0;
}
executing_ = NO;
finished_ = YES;
if (isSuccess) {
if ([self.delegate respondsToSelector:@selector(didFinishDownloadFile:)]) {
[self.delegate didFinishDownloadFile:self.userInfo];
}
} else {
if ([self.delegate respondsToSelector:@selector(didFailToDownloadFile:)]) {
[self.delegate didFailToDownloadFile:self.userInfo];
}
}
}
-(void)cancelled {
// Code for cancelled
error_ = [[NSError alloc] initWithDomain:@"DownloadFileOperation" code:123 userInfo:nil];
[self done:NO];
}
- (void)start
{
// Ensure this operation is not being restarted and that it has not been cancelled
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(start)
withObject:nil waitUntilDone:NO];
return;
}
if( finished_ || [self isCancelled] ) { [self done:NO]; return; }
// From this point on, the operation is officially executing--remember, isExecuting
// needs to be KVO compliant!
executing_ = YES;
// Create the NSURLConnection--this could have been done in init, but we delayed
// until no in case the operation was never enqueued or was cancelled before starting
connection_ = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:connectionURL_
cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0]
delegate:self];
}
#pragma mark Overrides
- (BOOL)isConcurrent {
return YES;
}
- (BOOL)isExecuting {
return executing_;
}
- (BOOL)isFinished {
return finished_;
}
#pragma mark - Delegate Methods for NSURLConnection
// The connection failed
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
if([self isCancelled]) {
[self cancelled];
return;
}
else {
[self done:NO];
}
}
// The connection received more data
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if([self isCancelled]) {
[self cancelled];
return;
}
// dump the data
// Write to disk.
int success = [stream write:[data bytes] maxLength:[data length]];
if (success < 0) {
error_ = [[NSError alloc] initWithDomain:@"DownloadFileOperation" code:1 userInfo:[NSDictionary
dictionaryWithObject:@"Error writing to disk" forKey:NSLocalizedDescriptionKey]];
[self done:NO];
}
receivedSize_ = receivedSize_ + success;
if ([self.delegate respondsToSelector:@selector(didReceive:inTotal:userInfo:)]) {
[self.delegate didReceive:self.receivedSize inTotal:self.fileSize userInfo:self.userInfo];
}
}
// Initial response
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if([self isCancelled]) {
[self cancelled];
return;
}
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger statusCode = [httpResponse statusCode];
if( statusCode == 200 ) {
receivedSize_ = 0;
fileSize_ = [[httpResponse.allHeaderFields objectForKey:@"Content-Length"] longLongValue];
[stream open];
} else {
NSString* statusError = [NSString stringWithFormat:NSLocalizedString(@"HTTP Error: %ld", nil), statusCode];
NSDictionary* userInfo = [NSDictionary dictionaryWithObject:statusError forKey:NSLocalizedDescriptionKey];
error_ = [[NSError alloc] initWithDomain:@"DownloadFileOperation"
code:statusCode
userInfo:userInfo];
[self done:NO];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if([self isCancelled]) {
[self cancelled];
} else {
[self done:YES];
}
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
return nil;
}
@end
@implementation DownloadFileOperationQueue
+(DownloadFileOperationQueue*)sharedQueue
{
static DownloadFileOperationQueue *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[DownloadFileOperationQueue alloc] init];
});
return sharedInstance;
}
@end