Skip to content

Implement storage.download() for Android #154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 152 additions & 17 deletions android/src/main/java/io/fullstack/firestack/FirestackStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import android.content.Context;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.HashMap;

Expand All @@ -26,6 +29,8 @@
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;

import com.google.firebase.storage.StorageException;
import com.google.firebase.storage.StreamDownloadTask;
import com.google.firebase.storage.UploadTask;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageMetadata;
Expand All @@ -49,6 +54,18 @@ class FirestackStorageModule extends ReactContextBaseJavaModule {
private static final String FileTypeRegular = "FILETYPE_REGULAR";
private static final String FileTypeDirectory = "FILETYPE_DIRECTORY";

private static final String STORAGE_UPLOAD_PROGRESS = "upload_progress";
private static final String STORAGE_UPLOAD_PAUSED = "upload_paused";
private static final String STORAGE_UPLOAD_RESUMED = "upload_resumed";

private static final String STORAGE_DOWNLOAD_PROGRESS = "download_progress";
private static final String STORAGE_DOWNLOAD_PAUSED = "download_paused";
private static final String STORAGE_DOWNLOAD_RESUMED = "download_resumed";
private static final String STORAGE_DOWNLOAD_SUCCESS = "download_success";
private static final String STORAGE_DOWNLOAD_FAILURE = "download_failure";

private ReactContext mReactContext;

public FirestackStorageModule(ReactApplicationContext reactContext) {
super(reactContext);

Expand All @@ -60,6 +77,118 @@ public String getName() {
return TAG;
}


public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}

@ReactMethod
public void downloadFile(final String urlStr,
final String fbPath,
final String localFile,
final Callback callback) {
Log.d(TAG, "downloadFile: "+urlStr+", "+localFile);
if (!isExternalStorageWritable()) {
Log.w(TAG, "downloadFile failed: external storage not writable");
WritableMap error = Arguments.createMap();
final int errorCode = 1;
error.putDouble("code", errorCode);
error.putString("description", "downloadFile failed: external storage not writable");
callback.invoke(error);
return;
}
FirebaseStorage storage = FirebaseStorage.getInstance();
String storageBucket = storage.getApp().getOptions().getStorageBucket();
String storageUrl = "gs://" + storageBucket;
Log.d(TAG, "Storage url " + storageUrl + fbPath);

StorageReference storageRef = storage.getReferenceFromUrl(storageUrl);
StorageReference fileRef = storageRef.child(fbPath);

fileRef.getStream(new StreamDownloadTask.StreamProcessor() {
@Override
public void doInBackground(StreamDownloadTask.TaskSnapshot taskSnapshot, InputStream inputStream) throws IOException {
int indexOfLastSlash = localFile.lastIndexOf("/");
String pathMinusFileName = localFile.substring(0, indexOfLastSlash) + "/";
String filename = localFile.substring(indexOfLastSlash+1);
File fileWithJustPath = new File(pathMinusFileName);
if (!fileWithJustPath.mkdirs()) {
Log.e(TAG, "Directory not created");
WritableMap error = Arguments.createMap();
error.putString("message", "Directory not created");
callback.invoke(error);
return;
}
File fileWithFullPath = new File(pathMinusFileName, filename);
FileOutputStream output = new FileOutputStream(fileWithFullPath);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
output.close();
}
}).addOnProgressListener(new OnProgressListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onProgress(StreamDownloadTask.TaskSnapshot taskSnapshot) {
WritableMap data = Arguments.createMap();
data.putString("ref", taskSnapshot.getStorage().getBucket());
double percentComplete = taskSnapshot.getTotalByteCount() == 0 ? 0.0f : 100.0f * (taskSnapshot.getBytesTransferred()) / (taskSnapshot.getTotalByteCount());
data.putDouble("progress", percentComplete);
FirestackUtils.sendEvent(mReactContext, STORAGE_DOWNLOAD_PROGRESS, data);
}
}).addOnPausedListener(new OnPausedListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onPaused(StreamDownloadTask.TaskSnapshot taskSnapshot) {
WritableMap data = Arguments.createMap();
data.putString("ref", taskSnapshot.getStorage().getBucket());
FirestackUtils.sendEvent(mReactContext, STORAGE_DOWNLOAD_PAUSED, data);
}
}).addOnSuccessListener(new OnSuccessListener<StreamDownloadTask.TaskSnapshot>() {
@Override
public void onSuccess(StreamDownloadTask.TaskSnapshot taskSnapshot) {
final WritableMap data = Arguments.createMap();
StorageReference ref = taskSnapshot.getStorage();
data.putString("fullPath", ref.getPath());
data.putString("bucket", ref.getBucket());
data.putString("name", ref.getName());
ref.getMetadata().addOnSuccessListener(new OnSuccessListener<StorageMetadata>() {
@Override
public void onSuccess(final StorageMetadata storageMetadata) {
data.putMap("metadata", getMetadataAsMap(storageMetadata));
callback.invoke(null, data);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
final int errorCode = 1;
WritableMap data = Arguments.createMap();
StorageException storageException = StorageException.fromException(exception);
data.putString("description", storageException.getMessage());
data.putInt("code", errorCode);
callback.invoke(makeErrorPayload(errorCode, exception));
}
});
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
final int errorCode = 1;
WritableMap data = Arguments.createMap();
StorageException storageException = StorageException.fromException(exception);
data.putString("description", storageException.getMessage());
data.putInt("code", errorCode);
callback.invoke(makeErrorPayload(errorCode, exception));
}
});
}

@ReactMethod
public void downloadUrl(final String javascriptStorageBucket,
final String path,
Expand Down Expand Up @@ -90,16 +219,7 @@ public void onSuccess(Uri uri) {
public void onSuccess(final StorageMetadata storageMetadata) {
Log.d(TAG, "getMetadata success " + storageMetadata);

WritableMap metadata = Arguments.createMap();
metadata.putString("getBucket", storageMetadata.getBucket());
metadata.putString("getName", storageMetadata.getName());
metadata.putDouble("sizeBytes", storageMetadata.getSizeBytes());
metadata.putDouble("created_at", storageMetadata.getCreationTimeMillis());
metadata.putDouble("updated_at", storageMetadata.getUpdatedTimeMillis());
metadata.putString("md5hash", storageMetadata.getMd5Hash());
metadata.putString("encoding", storageMetadata.getContentEncoding());

res.putMap("metadata", metadata);
res.putMap("metadata", getMetadataAsMap(storageMetadata));
res.putString("name", storageMetadata.getName());
res.putString("url", storageMetadata.getDownloadUrl().toString());
callback.invoke(null, res);
Expand All @@ -109,7 +229,8 @@ public void onSuccess(final StorageMetadata storageMetadata) {
@Override
public void onFailure(@NonNull Exception exception) {
Log.e(TAG, "Failure in download " + exception);
callback.invoke(makeErrorPayload(1, exception));
final int errorCode = 1;
callback.invoke(makeErrorPayload(errorCode, exception));
}
});

Expand All @@ -129,6 +250,18 @@ public void onFailure(@NonNull Exception exception) {
});
}

private WritableMap getMetadataAsMap(StorageMetadata storageMetadata) {
WritableMap metadata = Arguments.createMap();
metadata.putString("getBucket", storageMetadata.getBucket());
metadata.putString("getName", storageMetadata.getName());
metadata.putDouble("sizeBytes", storageMetadata.getSizeBytes());
metadata.putDouble("created_at", storageMetadata.getCreationTimeMillis());
metadata.putDouble("updated_at", storageMetadata.getUpdatedTimeMillis());
metadata.putString("md5hash", storageMetadata.getMd5Hash());
metadata.putString("encoding", storageMetadata.getContentEncoding());
return metadata;
}

// STORAGE
@ReactMethod
public void uploadFile(final String urlStr, final String name, final String filepath, final ReadableMap metadata, final Callback callback) {
Expand Down Expand Up @@ -191,9 +324,9 @@ public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {

if (progress >= 0) {
WritableMap data = Arguments.createMap();
data.putString("eventName", "upload_progress");
data.putString("eventName", STORAGE_UPLOAD_PROGRESS);
data.putDouble("progress", progress);
FirestackUtils.sendEvent(getReactApplicationContext(), "upload_progress", data);
FirestackUtils.sendEvent(getReactApplicationContext(), STORAGE_UPLOAD_PROGRESS, data);
}
}
})
Expand All @@ -204,13 +337,14 @@ public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
StorageMetadata d = taskSnapshot.getMetadata();
String bucket = d.getBucket();
WritableMap data = Arguments.createMap();
data.putString("eventName", "upload_paused");
data.putString("eventName", STORAGE_UPLOAD_PAUSED);
data.putString("ref", bucket);
FirestackUtils.sendEvent(getReactApplicationContext(), "upload_paused", data);
FirestackUtils.sendEvent(getReactApplicationContext(), STORAGE_UPLOAD_PAUSED, data);
}
});
} catch (Exception ex) {
callback.invoke(makeErrorPayload(2, ex));
final int errorCode = 2;
callback.invoke(makeErrorPayload(errorCode, ex));
}
}

Expand All @@ -221,7 +355,8 @@ public void getRealPathFromURI(final String uri, final Callback callback) {
callback.invoke(null, path);
} catch (Exception ex) {
ex.printStackTrace();
callback.invoke(makeErrorPayload(1, ex));
final int errorCode = 1;
callback.invoke(makeErrorPayload(errorCode, ex));
}
}

Expand Down
Loading