Skip to content

Commit b603084

Browse files
committed
Refactored downloadFile, added stopDownload
1 parent de4f913 commit b603084

File tree

10 files changed

+303
-121
lines changed

10 files changed

+303
-121
lines changed

Downloader.h

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
#import <Foundation/Foundation.h>
22

3+
typedef void (^DownloaderCallback)(NSNumber*, NSNumber*);
34
typedef void (^ErrorCallback)(NSError*);
4-
typedef void (^DownloaderCallback)(NSNumber*, NSNumber*, NSNumber*);
5+
typedef void (^BeginCallback)(NSNumber*, NSNumber*, NSDictionary*);
6+
typedef void (^ProgressCallback)(NSNumber*, NSNumber*);
7+
8+
@interface DownloadParams : NSObject
9+
10+
@property (copy) NSString* fromUrl;
11+
@property (copy) NSString* toFile;
12+
@property (copy) DownloaderCallback callback; // Download has finished (data written)
13+
@property (copy) ErrorCallback errorCallback; // Something went wrong
14+
@property (copy) BeginCallback beginCallback; // Download has started (headers received)
15+
@property (copy) ProgressCallback progressCallback; // Download is progressing
16+
17+
@end
518

619
@interface Downloader : NSObject <NSURLConnectionDelegate>
720

8-
- (void)downloadFile:(NSString*)urlStr toFile:(NSString*)downloadPath callback:(DownloaderCallback)callback errorCallback:(ErrorCallback)errorCallback progressCallback:(DownloaderCallback)progressCallback;
21+
- (void)downloadFile:(DownloadParams*)params;
22+
- (void)stopDownload;
923

1024
@end

Downloader.m

+27-19
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#import "Downloader.h"
22

3+
@implementation DownloadParams
4+
5+
@end
6+
37
@interface Downloader()
48

5-
@property (copy) DownloaderCallback callback;
6-
@property (copy) ErrorCallback errorCallback;
7-
@property (copy) DownloaderCallback progressCallback;
9+
@property (copy) DownloadParams* params;
810

11+
@property (retain) NSURLConnection* connection;
912
@property (retain) NSNumber* statusCode;
1013
@property (retain) NSNumber* contentLength;
1114
@property (retain) NSNumber* bytesWritten;
@@ -16,42 +19,40 @@ @interface Downloader()
1619

1720
@implementation Downloader
1821

19-
- (void)downloadFile:(NSString*)urlStr toFile:(NSString*)downloadPath callback:(DownloaderCallback)callback errorCallback:(ErrorCallback)errorCallback progressCallback:(DownloaderCallback)progressCallback
22+
- (void)downloadFile:(DownloadParams*)params
2023
{
21-
_callback = callback;
22-
_errorCallback = errorCallback;
23-
_progressCallback = progressCallback;
24-
24+
_params = params;
25+
2526
_bytesWritten = 0;
2627

27-
NSURL* url = [NSURL URLWithString:urlStr];
28+
NSURL* url = [NSURL URLWithString:_params.fromUrl];
2829

2930
NSMutableURLRequest* downloadRequest = [NSMutableURLRequest requestWithURL:url
3031
cachePolicy:NSURLRequestUseProtocolCachePolicy
3132
timeoutInterval:30];
3233

33-
[[NSFileManager defaultManager] createFileAtPath:downloadPath contents:nil attributes:nil];
34+
[[NSFileManager defaultManager] createFileAtPath:_params.toFile contents:nil attributes:nil];
3435

35-
_fileHandle = [NSFileHandle fileHandleForWritingAtPath:downloadPath];
36+
_fileHandle = [NSFileHandle fileHandleForWritingAtPath:_params.toFile];
3637

3738
if (!_fileHandle) {
38-
NSError* error = [NSError errorWithDomain:@"Downloader" code:NSURLErrorFileDoesNotExist userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"Failed to create target file at path: %@", downloadPath]}];
39+
NSError* error = [NSError errorWithDomain:@"Downloader" code:NSURLErrorFileDoesNotExist userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"Failed to create target file at path: %@", _params.toFile]}];
3940

40-
return _errorCallback(error);
41+
return _params.errorCallback(error);
4142
}
4243

43-
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self startImmediately:NO];
44+
_connection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self startImmediately:NO];
4445

45-
[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
46+
[_connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
4647

47-
[connection start];
48+
[_connection start];
4849
}
4950

5051
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
5152
{
5253
[_fileHandle closeFile];
5354

54-
return _errorCallback(error);
55+
return _params.errorCallback(error);
5556
}
5657

5758
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
@@ -60,6 +61,8 @@ - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLRespons
6061

6162
_statusCode = [NSNumber numberWithLong:httpUrlResponse.statusCode];
6263
_contentLength = [NSNumber numberWithLong: httpUrlResponse.expectedContentLength];
64+
65+
return _params.beginCallback(_statusCode, _contentLength, httpUrlResponse.allHeaderFields);
6366
}
6467

6568
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
@@ -69,15 +72,20 @@ - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
6972

7073
_bytesWritten = [NSNumber numberWithUnsignedInteger:[_bytesWritten unsignedIntegerValue] + data.length];
7174

72-
return _progressCallback(_statusCode, _contentLength, _bytesWritten);
75+
return _params.progressCallback(_contentLength, _bytesWritten);
7376
}
7477
}
7578

7679
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
7780
{
7881
[_fileHandle closeFile];
7982

80-
return _callback(_statusCode, _contentLength, _bytesWritten);
83+
return _params.callback(_statusCode, _bytesWritten);
84+
}
85+
86+
- (void)stopDownload
87+
{
88+
[_connection cancel];
8189
}
8290

8391
@end

FS.common.js

+15-4
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,30 @@ var RNFS = {
138138
.catch(convertError);
139139
},
140140

141-
downloadFile(url, filepath, progress) {
141+
downloadFile(fromUrl, toFile, begin, progress) {
142142
var jobId = getJobId();
143143
var subscriptionIos, subscriptionAndroid;
144144

145-
if (progress) {
145+
if (!begin) begin = (info) => {
146+
console.log('Download begun:', info);
147+
};
148+
149+
if (begin) {
146150
// Two different styles of subscribing to events for different platforms, hmmm....
147151
if (NativeAppEventEmitter.addListener)
148-
subscriptionIos = NativeAppEventEmitter.addListener('DownloadProgress-' + jobId, progress);
152+
subscriptionIos = NativeAppEventEmitter.addListener('DownloadBegin-' + jobId, begin);
153+
if (DeviceEventEmitter.addListener)
154+
subscriptionAndroid = DeviceEventEmitter.addListener('DownloadBegin-' + jobId, begin);
155+
}
156+
157+
if (progress) {
149158
if (NativeAppEventEmitter.addListener)
159+
subscriptionIos = NativeAppEventEmitter.addListener('DownloadProgress-' + jobId, progress);
160+
if (DeviceEventEmitter.addListener)
150161
subscriptionAndroid = DeviceEventEmitter.addListener('DownloadProgress-' + jobId, progress);
151162
}
152163

153-
return _downloadFile(url, filepath, jobId)
164+
return _downloadFile(fromUrl, toFile, jobId)
154165
.then(res => {
155166
if (subscriptionIos) subscriptionIos.remove();
156167
if (subscriptionAndroid) subscriptionAndroid.remove();

RNFS.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
8BF740771C033A2E0057A1E7 /* Downloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF740761C033A2E0057A1E7 /* Downloader.m */; };
1011
F1E59BDF1ADD662800ACA28A /* RNFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E59BDE1ADD662800ACA28A /* RNFSManager.m */; };
1112
F1EB08BB1AFD0E6A008F8F2B /* NSArray+Map.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */; };
1213
/* End PBXBuildFile section */
@@ -24,6 +25,8 @@
2425
/* End PBXCopyFilesBuildPhase section */
2526

2627
/* Begin PBXFileReference section */
28+
8BF740751C033A2E0057A1E7 /* Downloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Downloader.h; sourceTree = "<group>"; };
29+
8BF740761C033A2E0057A1E7 /* Downloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Downloader.m; sourceTree = "<group>"; };
2730
F12AFB9B1ADAF8F800E0535D /* libRNFS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFS.a; sourceTree = BUILT_PRODUCTS_DIR; };
2831
F1E59BDD1ADD662800ACA28A /* RNFSManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFSManager.h; sourceTree = "<group>"; };
2932
F1E59BDE1ADD662800ACA28A /* RNFSManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFSManager.m; sourceTree = "<group>"; };
@@ -49,6 +52,8 @@
4952
F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */,
5053
F1E59BDD1ADD662800ACA28A /* RNFSManager.h */,
5154
F1E59BDE1ADD662800ACA28A /* RNFSManager.m */,
55+
8BF740751C033A2E0057A1E7 /* Downloader.h */,
56+
8BF740761C033A2E0057A1E7 /* Downloader.m */,
5257
F12AFB9C1ADAF8F800E0535D /* Products */,
5358
);
5459
sourceTree = "<group>";
@@ -119,6 +124,7 @@
119124
files = (
120125
F1E59BDF1ADD662800ACA28A /* RNFSManager.m in Sources */,
121126
F1EB08BB1AFD0E6A008F8F2B /* NSArray+Map.m in Sources */,
127+
8BF740771C033A2E0057A1E7 /* Downloader.m in Sources */,
122128
);
123129
runOnlyForDeploymentPostprocessing = 0;
124130
};

RNFSManager.m

+42-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
#import "Downloader.h"
1313
#import "RCTEventDispatcher.h"
1414

15+
@interface RNFSManager()
16+
17+
@property (retain) NSMutableDictionary* downloaders;
18+
19+
@end
20+
1521
@implementation RNFSManager
1622

1723
@synthesize bridge = _bridge;
@@ -147,25 +153,52 @@ - (dispatch_queue_t)methodQueue
147153
jobId:(nonnull NSNumber *)jobId
148154
callback:(RCTResponseSenderBlock)callback)
149155
{
150-
151-
DownloaderCallback downloaderSuccessCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSNumber* bytesWritten) {
152-
return callback(@[[NSNull null], [NSNumber numberWithBool:YES], filepath]);
156+
157+
DownloadParams* params = [DownloadParams alloc];
158+
159+
params.fromUrl = urlStr;
160+
params.toFile = filepath;
161+
162+
params.callback = ^(NSNumber* statusCode, NSNumber* bytesWritten) {
163+
return callback(@[[NSNull null], @{@"jobId": jobId,
164+
@"statusCode": statusCode,
165+
@"bytesWritten": bytesWritten}]);
153166
};
154167

155-
ErrorCallback downloaderErrorCallback = ^(NSError* error) {
168+
params.errorCallback = ^(NSError* error) {
156169
return callback([self makeErrorPayload:error]);
157170
};
158-
159-
DownloaderCallback downloaderProgressCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSNumber* bytesWritten) {
160-
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadProgress-%@", jobId]
161-
body:@{@"statusCode": statusCode,
171+
172+
params.beginCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSDictionary* headers) {
173+
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadBegin-%@", jobId]
174+
body:@{@"jobId": jobId,
175+
@"statusCode": statusCode,
162176
@"contentLength": contentLength,
177+
@"headers": headers}];
178+
};
179+
180+
params.progressCallback = ^(NSNumber* contentLength, NSNumber* bytesWritten) {
181+
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadProgress-%@", jobId]
182+
body:@{@"contentLength": contentLength,
163183
@"bytesWritten": bytesWritten}];
164184
};
165185

186+
if (self.downloaders) self.downloaders = [NSMutableDictionary alloc];
187+
166188
Downloader* downloader = [Downloader alloc];
167189

168-
[downloader downloadFile:urlStr toFile:filepath callback:downloaderSuccessCallback errorCallback:downloaderErrorCallback progressCallback:downloaderProgressCallback];
190+
[downloader downloadFile:params];
191+
192+
[self.downloaders setValue:downloader forKey:[jobId stringValue]];
193+
}
194+
195+
RCT_EXPORT_METHOD(stopDownload:(NSNumber *)jobId)
196+
{
197+
Downloader* downloader = [self.downloaders objectForKey:[jobId stringValue]];
198+
199+
if (downloader != nil) {
200+
[downloader stopDownload];
201+
}
169202
}
170203

171204
RCT_EXPORT_METHOD(pathForBundle:(NSString *)bundleNamed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.rnfs;
2+
3+
import java.io.File;
4+
import java.net.URL;
5+
import java.util.*;
6+
7+
public class DownloadParams {
8+
public interface OnTaskCompleted {
9+
void onTaskCompleted(DownloadResult res);
10+
}
11+
12+
public interface OnDownloadBegin {
13+
void onDownloadBegin(int statusCode, int contentLength, Map<String, String> headers);
14+
}
15+
16+
public interface OnDownloadProgress {
17+
void onDownloadProgress(int contentLength, int bytesWritten);
18+
}
19+
20+
public URL src;
21+
public File dest;
22+
public OnTaskCompleted onTaskCompleted;
23+
public OnDownloadBegin onDownloadBegin;
24+
public OnDownloadProgress onDownloadProgress;
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.rnfs;
2+
3+
public class DownloadResult {
4+
public int statusCode;
5+
public int bytesWritten;
6+
public Exception exception;
7+
}

0 commit comments

Comments
 (0)