Skip to content

Commit

Permalink
Refactored downloadFile, added stopDownload
Browse files Browse the repository at this point in the history
  • Loading branch information
cjdell committed Nov 23, 2015
1 parent de4f913 commit b603084
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 121 deletions.
18 changes: 16 additions & 2 deletions Downloader.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
#import <Foundation/Foundation.h>

typedef void (^DownloaderCallback)(NSNumber*, NSNumber*);
typedef void (^ErrorCallback)(NSError*);
typedef void (^DownloaderCallback)(NSNumber*, NSNumber*, NSNumber*);
typedef void (^BeginCallback)(NSNumber*, NSNumber*, NSDictionary*);
typedef void (^ProgressCallback)(NSNumber*, NSNumber*);

@interface DownloadParams : NSObject

@property (copy) NSString* fromUrl;
@property (copy) NSString* toFile;
@property (copy) DownloaderCallback callback; // Download has finished (data written)
@property (copy) ErrorCallback errorCallback; // Something went wrong
@property (copy) BeginCallback beginCallback; // Download has started (headers received)
@property (copy) ProgressCallback progressCallback; // Download is progressing

@end

@interface Downloader : NSObject <NSURLConnectionDelegate>

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

@end
46 changes: 27 additions & 19 deletions Downloader.m
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#import "Downloader.h"

@implementation DownloadParams

@end

@interface Downloader()

@property (copy) DownloaderCallback callback;
@property (copy) ErrorCallback errorCallback;
@property (copy) DownloaderCallback progressCallback;
@property (copy) DownloadParams* params;

@property (retain) NSURLConnection* connection;
@property (retain) NSNumber* statusCode;
@property (retain) NSNumber* contentLength;
@property (retain) NSNumber* bytesWritten;
Expand All @@ -16,42 +19,40 @@ @interface Downloader()

@implementation Downloader

- (void)downloadFile:(NSString*)urlStr toFile:(NSString*)downloadPath callback:(DownloaderCallback)callback errorCallback:(ErrorCallback)errorCallback progressCallback:(DownloaderCallback)progressCallback
- (void)downloadFile:(DownloadParams*)params
{
_callback = callback;
_errorCallback = errorCallback;
_progressCallback = progressCallback;

_params = params;

_bytesWritten = 0;

NSURL* url = [NSURL URLWithString:urlStr];
NSURL* url = [NSURL URLWithString:_params.fromUrl];

NSMutableURLRequest* downloadRequest = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30];

[[NSFileManager defaultManager] createFileAtPath:downloadPath contents:nil attributes:nil];
[[NSFileManager defaultManager] createFileAtPath:_params.toFile contents:nil attributes:nil];

_fileHandle = [NSFileHandle fileHandleForWritingAtPath:downloadPath];
_fileHandle = [NSFileHandle fileHandleForWritingAtPath:_params.toFile];

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

return _errorCallback(error);
return _params.errorCallback(error);
}

NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self startImmediately:NO];
_connection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self startImmediately:NO];

[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[_connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

[connection start];
[_connection start];
}

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

return _errorCallback(error);
return _params.errorCallback(error);
}

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

_statusCode = [NSNumber numberWithLong:httpUrlResponse.statusCode];
_contentLength = [NSNumber numberWithLong: httpUrlResponse.expectedContentLength];

return _params.beginCallback(_statusCode, _contentLength, httpUrlResponse.allHeaderFields);
}

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

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

return _progressCallback(_statusCode, _contentLength, _bytesWritten);
return _params.progressCallback(_contentLength, _bytesWritten);
}
}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
[_fileHandle closeFile];

return _callback(_statusCode, _contentLength, _bytesWritten);
return _params.callback(_statusCode, _bytesWritten);
}

- (void)stopDownload
{
[_connection cancel];
}

@end
19 changes: 15 additions & 4 deletions FS.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,30 @@ var RNFS = {
.catch(convertError);
},

downloadFile(url, filepath, progress) {
downloadFile(fromUrl, toFile, begin, progress) {
var jobId = getJobId();
var subscriptionIos, subscriptionAndroid;

if (progress) {
if (!begin) begin = (info) => {
console.log('Download begun:', info);
};

if (begin) {
// Two different styles of subscribing to events for different platforms, hmmm....
if (NativeAppEventEmitter.addListener)
subscriptionIos = NativeAppEventEmitter.addListener('DownloadProgress-' + jobId, progress);
subscriptionIos = NativeAppEventEmitter.addListener('DownloadBegin-' + jobId, begin);
if (DeviceEventEmitter.addListener)
subscriptionAndroid = DeviceEventEmitter.addListener('DownloadBegin-' + jobId, begin);
}

if (progress) {
if (NativeAppEventEmitter.addListener)
subscriptionIos = NativeAppEventEmitter.addListener('DownloadProgress-' + jobId, progress);
if (DeviceEventEmitter.addListener)
subscriptionAndroid = DeviceEventEmitter.addListener('DownloadProgress-' + jobId, progress);
}

return _downloadFile(url, filepath, jobId)
return _downloadFile(fromUrl, toFile, jobId)
.then(res => {
if (subscriptionIos) subscriptionIos.remove();
if (subscriptionAndroid) subscriptionAndroid.remove();
Expand Down
6 changes: 6 additions & 0 deletions RNFS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
8BF740771C033A2E0057A1E7 /* Downloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF740761C033A2E0057A1E7 /* Downloader.m */; };
F1E59BDF1ADD662800ACA28A /* RNFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E59BDE1ADD662800ACA28A /* RNFSManager.m */; };
F1EB08BB1AFD0E6A008F8F2B /* NSArray+Map.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */; };
/* End PBXBuildFile section */
Expand All @@ -24,6 +25,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
8BF740751C033A2E0057A1E7 /* Downloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Downloader.h; sourceTree = "<group>"; };
8BF740761C033A2E0057A1E7 /* Downloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Downloader.m; sourceTree = "<group>"; };
F12AFB9B1ADAF8F800E0535D /* libRNFS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFS.a; sourceTree = BUILT_PRODUCTS_DIR; };
F1E59BDD1ADD662800ACA28A /* RNFSManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNFSManager.h; sourceTree = "<group>"; };
F1E59BDE1ADD662800ACA28A /* RNFSManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFSManager.m; sourceTree = "<group>"; };
Expand All @@ -49,6 +52,8 @@
F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */,
F1E59BDD1ADD662800ACA28A /* RNFSManager.h */,
F1E59BDE1ADD662800ACA28A /* RNFSManager.m */,
8BF740751C033A2E0057A1E7 /* Downloader.h */,
8BF740761C033A2E0057A1E7 /* Downloader.m */,
F12AFB9C1ADAF8F800E0535D /* Products */,
);
sourceTree = "<group>";
Expand Down Expand Up @@ -119,6 +124,7 @@
files = (
F1E59BDF1ADD662800ACA28A /* RNFSManager.m in Sources */,
F1EB08BB1AFD0E6A008F8F2B /* NSArray+Map.m in Sources */,
8BF740771C033A2E0057A1E7 /* Downloader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
51 changes: 42 additions & 9 deletions RNFSManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
#import "Downloader.h"
#import "RCTEventDispatcher.h"

@interface RNFSManager()

@property (retain) NSMutableDictionary* downloaders;

@end

@implementation RNFSManager

@synthesize bridge = _bridge;
Expand Down Expand Up @@ -147,25 +153,52 @@ - (dispatch_queue_t)methodQueue
jobId:(nonnull NSNumber *)jobId
callback:(RCTResponseSenderBlock)callback)
{

DownloaderCallback downloaderSuccessCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSNumber* bytesWritten) {
return callback(@[[NSNull null], [NSNumber numberWithBool:YES], filepath]);

DownloadParams* params = [DownloadParams alloc];

params.fromUrl = urlStr;
params.toFile = filepath;

params.callback = ^(NSNumber* statusCode, NSNumber* bytesWritten) {
return callback(@[[NSNull null], @{@"jobId": jobId,
@"statusCode": statusCode,
@"bytesWritten": bytesWritten}]);
};

ErrorCallback downloaderErrorCallback = ^(NSError* error) {
params.errorCallback = ^(NSError* error) {
return callback([self makeErrorPayload:error]);
};

DownloaderCallback downloaderProgressCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSNumber* bytesWritten) {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadProgress-%@", jobId]
body:@{@"statusCode": statusCode,

params.beginCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSDictionary* headers) {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadBegin-%@", jobId]
body:@{@"jobId": jobId,
@"statusCode": statusCode,
@"contentLength": contentLength,
@"headers": headers}];
};

params.progressCallback = ^(NSNumber* contentLength, NSNumber* bytesWritten) {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadProgress-%@", jobId]
body:@{@"contentLength": contentLength,
@"bytesWritten": bytesWritten}];
};

if (self.downloaders) self.downloaders = [NSMutableDictionary alloc];

Downloader* downloader = [Downloader alloc];

[downloader downloadFile:urlStr toFile:filepath callback:downloaderSuccessCallback errorCallback:downloaderErrorCallback progressCallback:downloaderProgressCallback];
[downloader downloadFile:params];

[self.downloaders setValue:downloader forKey:[jobId stringValue]];
}

RCT_EXPORT_METHOD(stopDownload:(NSNumber *)jobId)
{
Downloader* downloader = [self.downloaders objectForKey:[jobId stringValue]];

if (downloader != nil) {
[downloader stopDownload];
}
}

RCT_EXPORT_METHOD(pathForBundle:(NSString *)bundleNamed
Expand Down
25 changes: 25 additions & 0 deletions android/src/main/java/com/rnfs/DownloadParams.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.rnfs;

import java.io.File;
import java.net.URL;
import java.util.*;

public class DownloadParams {
public interface OnTaskCompleted {
void onTaskCompleted(DownloadResult res);
}

public interface OnDownloadBegin {
void onDownloadBegin(int statusCode, int contentLength, Map<String, String> headers);
}

public interface OnDownloadProgress {
void onDownloadProgress(int contentLength, int bytesWritten);
}

public URL src;
public File dest;
public OnTaskCompleted onTaskCompleted;
public OnDownloadBegin onDownloadBegin;
public OnDownloadProgress onDownloadProgress;
}
7 changes: 7 additions & 0 deletions android/src/main/java/com/rnfs/DownloadResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.rnfs;

public class DownloadResult {
public int statusCode;
public int bytesWritten;
public Exception exception;
}
Loading

0 comments on commit b603084

Please sign in to comment.