diff --git a/android/src/main/java/com/mybigday/rns3/RNS3TransferUtility.java b/android/src/main/java/com/mybigday/rns3/RNS3TransferUtility.java index 30fda61..e0940be 100644 --- a/android/src/main/java/com/mybigday/rns3/RNS3TransferUtility.java +++ b/android/src/main/java/com/mybigday/rns3/RNS3TransferUtility.java @@ -39,7 +39,7 @@ public static enum CredentialType { static { // default options - nativeCredentialsOptions.put("region", "eu-west-1"); + nativeCredentialsOptions.put("region", "us-east-1"); nativeCredentialsOptions.put("cognito_region", "eu-west-1"); } @@ -47,6 +47,7 @@ public static enum CredentialType { private Context context; private AmazonS3 s3; private TransferUtility transferUtility; + private Boolean subscribeProgress = true; public RNS3TransferUtility(ReactApplicationContext reactContext) { super(reactContext); @@ -94,19 +95,21 @@ public void onStateChanged(int id, TransferState state) { TransferObserver task = transferUtility.getTransferById(id); WritableMap result = Arguments.createMap(); result.putMap("task", convertTransferObserver(task)); - sendEvent("@_RNS3_Events", result); + sendEvent("@_RNS3_State_Changed", result); } @Override public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) { - TransferObserver task = transferUtility.getTransferById(id); - WritableMap result = Arguments.createMap(); - WritableMap taskMap = convertTransferObserver(task); - if (taskMap.getDouble("bytes") <= bytesTotal) { - taskMap.putDouble("bytes", bytesCurrent); - } - result.putMap("task", taskMap); - sendEvent("@_RNS3_Events", result); + if (subscribeProgress == true) { + TransferObserver task = transferUtility.getTransferById(id); + WritableMap result = Arguments.createMap(); + WritableMap taskMap = convertTransferObserver(task); + if (taskMap.getDouble("bytes") <= bytesTotal) { + taskMap.putDouble("bytes", bytesCurrent); + } + result.putMap("task", taskMap); + sendEvent("@_RNS3_Progress_Changed", result); + } } @Override @@ -115,7 +118,7 @@ public void onError(int id, Exception ex) { WritableMap result = Arguments.createMap(); result.putMap("task", convertTransferObserver(task)); result.putString("error", ex.getMessage()); - sendEvent("@_RNS3_Events", result); + sendEvent("@_RNS3_Error", result); } }); } @@ -151,14 +154,14 @@ private boolean setup(Map credentialsOptions) { } break; // TODO: support accountId, unauthRoleArn, authRoleArn - case COGNITO: + case COGNITO: String cognitoRegion = (String) credentialsOptions.get("cognito_region"); if (!(Boolean) credentialsOptions.get("caching")) { credentialsProvider = new CognitoCredentialsProvider( (String) credentialsOptions.get("identity_pool_id"), Regions.fromName(cognitoRegion) ); - } else { + } else { credentialsProvider = new CognitoCachingCredentialsProvider( context, (String) credentialsOptions.get("identity_pool_id"), @@ -182,9 +185,10 @@ private boolean setup(Map credentialsOptions) { } @ReactMethod - public void initializeRNS3() { + public void initializeRNS3(Boolean subscribeProgress) { if (alreadyInitialize) return; alreadyInitialize = true; + this.subscribeProgress = subscribeProgress; subscribeList(transferUtility.getTransfersWithType(TransferType.UPLOAD)); subscribeList(transferUtility.getTransfersWithType(TransferType.DOWNLOAD)); } @@ -252,7 +256,6 @@ public void download(ReadableMap options, Promise promise) { String bucket = options.getString("bucket"); String key = options.getString("key"); File file = new File(options.getString("file")); - TransferObserver task = transferUtility.download(bucket, key, file); subscribe(task); promise.resolve(convertTransferObserver(task)); diff --git a/example/app.js b/example/app.js index 79a4a76..6006cab 100644 --- a/example/app.js +++ b/example/app.js @@ -10,59 +10,61 @@ import React, { import { transferUtility } from "react-native-s3"; import fs from "react-native-fs"; -console.log(fs.DocumentDirectoryPath); - -const bucketName = ""; -const uploadFileKey = "test.mp4"; -const contentType = "image/jpeg"; -const uploadFilePath = fs.DocumentDirectoryPath + "/test.mp4"; -const downloadFileKey = "test.mp4"; -const downloadFilePath = fs.DocumentDirectoryPath + "/test_download.mp4"; +const bucketName = ""; // name of bucket +const uploadFileKey = "ReactNativeTest/test.mp4"; // path to file in s3, excluding bucket +const contentType = "image/jpeg"; // type of file +const uploadFilePath = fs.DocumentDirectoryPath + "/test.mp4"; // file to be uploaded +const downloadFileKey = "ReactNativeTest/hello_world.png"; // path to file in s3, excluding bucket +const downloadFilePath = fs.DocumentDirectoryPath + "/blah.png"; // path to where file should be downloaded to + +const subscribeProgress = true; // Change to false if you don't want to subscribe to progress events +var transferAction = ""; + + +// aws cognito options +const cognitoOptions = { + "region": "us-east-1", + "identity_pool_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "cognito_region": "us-east-1", + "caching": true +}; + +// aws access keys and region options for basic s3 use +// const keySecretOptions = { +// "access_key": "xxxx", +// "secret_key": "xxxxxxxxxxxxx", +// "region": "us-east-1" +// }; const sampleVideoURL = "http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"; -const styles = StyleSheet.create({ - container: { - flex: 1, - marginTop: 20, - backgroundColor: "#F5FCFF" - }, - title: { - fontSize: 20, - textAlign: "center", - margin: 10 - }, - task: { - flexDirection: "row", - justifyContent: "center" - }, - text: { - fontSize: 12, - textAlign: "center", - margin: 10 - }, - btn: { - fontSize: 15, - textAlign: "center", - margin: 10 - } -}); - class S3Sample extends Component { constructor(props) { super(props); this.state = { - initLoaded: false + initLoaded: false, + logText: "" }; } async componentDidMount() { if (!this.state.initLoaded) { if (!await fs.exists(uploadFilePath)) { - await fs.downloadFile(sampleVideoURL, uploadFilePath); + await fs.downloadFile(sampleVideoURL, uploadFilePath).then(() => { + fs.readDir(fs.DocumentDirectoryPath) + .then((result) => { + // Confirm that the file was written + console.log(result); + }); + }); } - await transferUtility.setupWithNative(); + + // Set up with cognito options + await transferUtility.setupWithCognito(cognitoOptions, subscribeProgress); + + // Set up with basic (standard) options + // await transferUtility.setupWithBasic(keySecretOptions, subscribeProgress); const uploadTasks = await transferUtility.getTasks("upload", true); const downloadTasks = await transferUtility.getTasks("download", true); @@ -74,13 +76,35 @@ class S3Sample extends Component { this.subscribeWithUpdateState(id, "downloadTasks"); } - this.setState({ initLoaded: true, uploadTasks, downloadTasks }); + this.setState({ initLoaded: true, logText: "Press Download or Upload to begin \n" }); } } + handleEvent = (eventType, task) => { + switch(eventType) { + case "@_RNS3_State_Changed": + if (task.state == "completed" && transferAction == "Download") { + this.setState({ logText: `${ this.state.logText }State_Changed: ${ task.state } \nDownload complete \nFile location: ${ fs.DocumentDirectoryPath }` }); + } else if (task.state == "completed" && transferAction == "Upload") { + this.setState({ logText: `${ this.state.logText }State_Changed: ${ task.state } \nUpload complete \ns3 file location: ${ bucketName }/${ uploadFileKey }` }); + } else { this.setState({ logText: `${ this.state.logText }State_Changed: ${ task.state } \n` }); } + break; + case "@_RNS3_Progress_Changed": + this.setState({ logText: `${ this.state.logText }Progress_Changed: ${ task.bytes/task.totalBytes * 100 }% \n` }); + break; + case "@_RNS3_Error": + this.setState({ logText: `${ this.state.logText }Error: ${ task.errMessage } \n\n` }); + break; + default: + console.warn("Receiving event that doesn't match case"); + break; + } + }; + subscribeWithUpdateState = (id, typeKey) => { transferUtility.subscribe(id, (err, task) => { - if (err) task.errMessage = err; + if (err != undefined) task.errMessage = err; + this.handleEvent(task.eventIdentifier, task); this.setState({ [typeKey]: { ...this.state[typeKey], @@ -91,6 +115,7 @@ class S3Sample extends Component { }; handleUploadFile = async () => { + transferAction = "Upload"; const task = await transferUtility.upload({ bucket: bucketName, key: uploadFileKey, @@ -103,12 +128,14 @@ class S3Sample extends Component { uploadTasks: { ...this.state.uploadTasks, ...{ [task.id]: task } - } + }, + logText: `${ this.state.logText }\nUpload Started To s3 Location:\n${ bucketName }/${ uploadFileKey } \n\n` }); this.subscribeWithUpdateState(task.id, "uploadTasks"); }; handleDownloadFile = async () => { + transferAction = "Download"; const task = await transferUtility.download({ bucket: bucketName, key: downloadFileKey, @@ -118,7 +145,8 @@ class S3Sample extends Component { downloadTasks: { ...this.state.downloadTasks, ...{ [task.id]: task } - } + }, + logText: `${ this.state.logText }\nDownload Started For File At s3 Location:\n${ bucketName }/${ downloadFileKey } \n\n` }); this.subscribeWithUpdateState(task.id, "downloadTasks"); }; @@ -146,81 +174,70 @@ class S3Sample extends Component { transferUtility.resume(id); } - renderTasks(tasks) { - return Object.keys(tasks).map(id => { - let progress; - if (tasks[id].totalBytes) { - progress = {(tasks[id].bytes / tasks[id].totalBytes) * 100 + "%"}; - } - return ( - - {id} - {tasks[id].state} - {progress} - - ); - }); - } - - renderUploadTask() { - const { uploadTasks } = this.state; - return ( - - {"Upload Tasks"} - {this.renderTasks(uploadTasks)} - - {"New Upload"} - - - ); - } - - renderDownloadTask() { - const { downloadTasks } = this.state; - return ( - - {"Download Tasks"} - {this.renderTasks(downloadTasks)} - - {"New Download"} - - - ); - } - - renderLoading() { - return ( - - {"Loading..."} - - ); - } - render() { return ( - - { - (() => { - if (!this.state.initLoaded) { - return this.renderLoading(); - } else { - return ( - - {this.renderUploadTask()} - {this.renderDownloadTask()} - - ); - } - })() - } + + {"Download Designated File"} + + + {"Upload Designated File"} + + {this.refs.scrollView.scrollTo({ y: height });}}> + + {this.state.logText} + ); } } +const styles = StyleSheet.create({ + container: { + flex: 1, + marginTop: 20, + alignItems: "center", + backgroundColor: "#F5FCFF" + }, + title: { + fontSize: 20, + textAlign: "center", + margin: 10 + }, + task: { + flexDirection: "row", + justifyContent: "center" + }, + logText: { + alignItems: "center", + paddingBottom: 20 + }, + text: { + fontSize: 12, + textAlign: "center", + margin: 10 + }, + btn: { + fontSize: 15, + textAlign: "center", + margin: 10 + }, + logContainer: { + flex: 1, + width: 350, + marginBottom: 10, + borderWidth: 2, + borderRadius: 5, + borderColor: "black", + paddingHorizontal: 10, + borderStyle: "solid", + backgroundColor: "lavender" + } +}); + AppRegistry.registerComponent("S3Sample", () => S3Sample); diff --git a/ios/RNS3/RNS3TransferUtility.m b/ios/RNS3/RNS3TransferUtility.m index 077022f..ab9a5ce 100644 --- a/ios/RNS3/RNS3TransferUtility.m +++ b/ios/RNS3/RNS3TransferUtility.m @@ -3,6 +3,7 @@ static NSMutableDictionary *nativeCredentialsOptions; static bool alreadyInitialize = false; +static bool subscribeProgress; @interface RNS3TransferUtility () @@ -130,18 +131,12 @@ - (BOOL)setup:(NSDictionary *)options { resolve(@([self setup:options])); } -- (void) sendEvent:(AWSS3TransferUtilityTask *)task type:(NSString *)type state:(NSString *)state bytes:(int64_t)bytes totalBytes:(int64_t)totalBytes error:(NSError *)error { +- (void) sendEvent:(AWSS3TransferUtilityTask *)task type:(NSString *)type state:(NSString *)state bytes:(int64_t)bytes totalBytes:(int64_t)totalBytes error:(NSError *)error label:(NSString *)label { NSDictionary *errorObj = nil; if (error) { - errorObj = @{ - @"domain":[error domain], - @"code": @([error code]), - @"description": [error localizedDescription] - }; - } - - [self.bridge.eventDispatcher - sendAppEventWithName:@"@_RNS3_Events" + errorObj = [error localizedDescription]; + [self.bridge.eventDispatcher + sendAppEventWithName:@"@_RNS3_Error" body:@{ @"task":@{ @"id":@([task taskIdentifier]), @@ -153,20 +148,40 @@ - (void) sendEvent:(AWSS3TransferUtilityTask *)task type:(NSString *)type state: }, @"type":type, @"error":errorObj ? errorObj : [NSNull null] - }]; + }]; + } else { + [self.bridge.eventDispatcher + sendAppEventWithName:label + body:@{ + @"task":@{ + @"id":@([task taskIdentifier]), + // @"bucket":[task bucket], + // @"key":[task key], + @"state":state, + @"bytes":@(bytes), + @"totalBytes":@(totalBytes) + }, + @"type":type, + @"error":errorObj ? errorObj : [NSNull null] + }]; + } } -RCT_EXPORT_METHOD(initializeRNS3) { +RCT_EXPORT_METHOD(initializeRNS3: (bool)subscribeProgressValue) { if (alreadyInitialize) return; alreadyInitialize = true; + subscribeProgress = subscribeProgressValue; self.uploadProgress = ^(AWSS3TransferUtilityTask *task, NSProgress *progress) { NSLog(@"update"); - [self sendEvent:task - type:@"upload" - state:@"in_progress" - bytes:progress.completedUnitCount - totalBytes:progress.totalUnitCount - error:nil]; + if (subscribeProgress == true) { + [self sendEvent:task + type:@"upload" + state:@"in_progress" + bytes:progress.completedUnitCount + totalBytes:progress.totalUnitCount + error:nil + label:@"@_RNS3_Progress_Changed"]; + } }; self.completionUploadHandler = ^(AWSS3TransferUtilityUploadTask *task, NSError *error) { NSString *state; @@ -176,16 +191,20 @@ - (void) sendEvent:(AWSS3TransferUtilityTask *)task type:(NSString *)type state: state:state bytes:0 totalBytes:0 - error:error]; + error:error + label:@"@_RNS3_State_Changed"]; }; self.downloadProgress = ^(AWSS3TransferUtilityTask *task, NSProgress *progress) { - [self sendEvent:task - type:@"download" - state:@"in_progress" - bytes:progress.completedUnitCount - totalBytes:progress.totalUnitCount - error:nil]; + if (subscribeProgress == true) { + [self sendEvent:task + type:@"download" + state:@"in_progress" + bytes:progress.completedUnitCount + totalBytes:progress.totalUnitCount + error:nil + label:@"@_RNS3_Progress_Changed"]; + } }; self.completionDownloadHandler = ^(AWSS3TransferUtilityDownloadTask *task, NSURL *location, NSData *data, NSError *error) { NSString *state; @@ -195,7 +214,8 @@ - (void) sendEvent:(AWSS3TransferUtilityTask *)task type:(NSString *)type state: state:state bytes:0 totalBytes:0 - error:error]; + error:error + label:@"@_RNS3_State_Changed"]; }; AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility S3TransferUtilityForKey:@"RNS3TransferUtility"]; diff --git a/src/TransferUtility.js b/src/TransferUtility.js index b87653a..4277d9d 100644 --- a/src/TransferUtility.js +++ b/src/TransferUtility.js @@ -81,16 +81,16 @@ async function setTaskExtra(task, values, isNew) { } export default class TransferUtility { - async setupWithNative() { + async setupWithNative(subscribeProgress = true) { const result = await RNS3TransferUtility.setupWithNative(); if (result) { await getTaskExtras(); - RNS3TransferUtility.initializeRNS3(); + RNS3TransferUtility.initializeRNS3(subscribeProgress); } return result; } - async setupWithBasic(options = {}) { + async setupWithBasic(options = {}, subscribeProgress = true) { if (!options.access_key || !options.secret_key) { return false; } @@ -100,19 +100,19 @@ export default class TransferUtility { const result = await RNS3TransferUtility.setupWithBasic({ ...defaultOptions, ...options}); if (result) { await getTaskExtras(); - RNS3TransferUtility.initializeRNS3(); + RNS3TransferUtility.initializeRNS3(subscribeProgress); } return result; } - async setupWithCognito(options = {}) { + async setupWithCognito(options = {}, subscribeProgress = true) { if (!options.identity_pool_id) { return false; } const result = await RNS3TransferUtility.setupWithBasic({ ...defaultCognitoOptions, ...options }); if (result) { await getTaskExtras(); - RNS3TransferUtility.initializeRNS3(); + RNS3TransferUtility.initializeRNS3(subscribeProgress); } return result; }