4
4
import android .os .Environment ;
5
5
6
6
import java .io .File ;
7
+ import java .io .FileOutputStream ;
8
+ import java .io .IOException ;
9
+ import java .io .InputStream ;
7
10
import java .util .Map ;
8
11
import java .util .HashMap ;
9
12
17
20
import com .facebook .react .bridge .WritableMap ;
18
21
import com .facebook .react .bridge .ReactMethod ;
19
22
import com .facebook .react .bridge .ReadableMap ;
23
+ import com .facebook .react .bridge .ReactContext ;
20
24
import com .facebook .react .bridge .ReactApplicationContext ;
21
25
import com .facebook .react .bridge .ReactContextBaseJavaModule ;
22
26
23
27
import com .google .android .gms .tasks .Task ;
24
28
import com .google .android .gms .tasks .OnFailureListener ;
25
29
import com .google .android .gms .tasks .OnSuccessListener ;
26
30
31
+ import com .google .firebase .storage .StorageException ;
32
+ import com .google .firebase .storage .StreamDownloadTask ;
27
33
import com .google .firebase .storage .UploadTask ;
28
34
import com .google .firebase .storage .FirebaseStorage ;
29
35
import com .google .firebase .storage .StorageMetadata ;
@@ -49,6 +55,18 @@ public class FirestackStorage extends ReactContextBaseJavaModule {
49
55
private static final String FileTypeRegular = "FILETYPE_REGULAR" ;
50
56
private static final String FileTypeDirectory = "FILETYPE_DIRECTORY" ;
51
57
58
+ private static final String STORAGE_UPLOAD_PROGRESS = "upload_progress" ;
59
+ private static final String STORAGE_UPLOAD_PAUSED = "upload_paused" ;
60
+ private static final String STORAGE_UPLOAD_RESUMED = "upload_resumed" ;
61
+
62
+ private static final String STORAGE_DOWNLOAD_PROGRESS = "download_progress" ;
63
+ private static final String STORAGE_DOWNLOAD_PAUSED = "download_paused" ;
64
+ private static final String STORAGE_DOWNLOAD_RESUMED = "download_resumed" ;
65
+ private static final String STORAGE_DOWNLOAD_SUCCESS = "download_success" ;
66
+ private static final String STORAGE_DOWNLOAD_FAILURE = "download_failure" ;
67
+
68
+ private ReactContext mReactContext ;
69
+
52
70
public FirestackStorage (ReactApplicationContext reactContext ) {
53
71
super (reactContext );
54
72
@@ -60,14 +78,123 @@ public String getName() {
60
78
return TAG ;
61
79
}
62
80
81
+
82
+ public boolean isExternalStorageWritable () {
83
+ String state = Environment .getExternalStorageState ();
84
+ return Environment .MEDIA_MOUNTED .equals (state );
85
+ }
86
+
87
+ @ ReactMethod
88
+ public void downloadFile (final String urlStr ,
89
+ final String fbPath ,
90
+ final String localFile ,
91
+ final Callback callback ) {
92
+ Log .d (TAG , "downloadFile: " + urlStr + ", " + localFile );
93
+ if (!isExternalStorageWritable ()) {
94
+ Log .w (TAG , "downloadFile failed: external storage not writable" );
95
+ WritableMap error = Arguments .createMap ();
96
+ final int errorCode = 1 ;
97
+ error .putDouble ("code" , errorCode );
98
+ error .putString ("description" , "downloadFile failed: external storage not writable" );
99
+ callback .invoke (error );
100
+ return ;
101
+ }
102
+ FirebaseStorage storage = FirebaseStorage .getInstance ();
103
+ String storageBucket = storage .getApp ().getOptions ().getStorageBucket ();
104
+ String storageUrl = "gs://" + storageBucket ;
105
+ Log .d (TAG , "Storage url " + storageUrl + fbPath );
106
+
107
+ StorageReference storageRef = storage .getReferenceFromUrl (storageUrl );
108
+ StorageReference fileRef = storageRef .child (fbPath );
109
+
110
+ fileRef .getStream (new StreamDownloadTask .StreamProcessor () {
111
+ @ Override
112
+ public void doInBackground (StreamDownloadTask .TaskSnapshot taskSnapshot , InputStream inputStream ) throws IOException {
113
+ int indexOfLastSlash = localFile .lastIndexOf ("/" );
114
+ String pathMinusFileName = localFile .substring (0 , indexOfLastSlash ) + "/" ;
115
+ String filename = localFile .substring (indexOfLastSlash + 1 );
116
+ File fileWithJustPath = new File (pathMinusFileName );
117
+ if (!fileWithJustPath .mkdirs ()) {
118
+ Log .e (TAG , "Directory not created" );
119
+ WritableMap error = Arguments .createMap ();
120
+ error .putString ("message" , "Directory not created" );
121
+ callback .invoke (error );
122
+ return ;
123
+ }
124
+ File fileWithFullPath = new File (pathMinusFileName , filename );
125
+ FileOutputStream output = new FileOutputStream (fileWithFullPath );
126
+ int bufferSize = 1024 ;
127
+ byte [] buffer = new byte [bufferSize ];
128
+ int len = 0 ;
129
+ while ((len = inputStream .read (buffer )) != -1 ) {
130
+ output .write (buffer , 0 , len );
131
+ }
132
+ output .close ();
133
+ }
134
+ }).addOnProgressListener (new OnProgressListener <StreamDownloadTask .TaskSnapshot >() {
135
+ @ Override
136
+ public void onProgress (StreamDownloadTask .TaskSnapshot taskSnapshot ) {
137
+ WritableMap data = Arguments .createMap ();
138
+ data .putString ("ref" , taskSnapshot .getStorage ().getBucket ());
139
+ double percentComplete = taskSnapshot .getTotalByteCount () == 0 ? 0.0f : 100.0f * (taskSnapshot .getBytesTransferred ()) / (taskSnapshot .getTotalByteCount ());
140
+ data .putDouble ("progress" , percentComplete );
141
+ Utils .sendEvent (mReactContext , STORAGE_DOWNLOAD_PROGRESS , data );
142
+ }
143
+ }).addOnPausedListener (new OnPausedListener <StreamDownloadTask .TaskSnapshot >() {
144
+ @ Override
145
+ public void onPaused (StreamDownloadTask .TaskSnapshot taskSnapshot ) {
146
+ WritableMap data = Arguments .createMap ();
147
+ data .putString ("ref" , taskSnapshot .getStorage ().getBucket ());
148
+ Utils .sendEvent (mReactContext , STORAGE_DOWNLOAD_PAUSED , data );
149
+ }
150
+ }).addOnSuccessListener (new OnSuccessListener <StreamDownloadTask .TaskSnapshot >() {
151
+ @ Override
152
+ public void onSuccess (StreamDownloadTask .TaskSnapshot taskSnapshot ) {
153
+ final WritableMap data = Arguments .createMap ();
154
+ StorageReference ref = taskSnapshot .getStorage ();
155
+ data .putString ("fullPath" , ref .getPath ());
156
+ data .putString ("bucket" , ref .getBucket ());
157
+ data .putString ("name" , ref .getName ());
158
+ ref .getMetadata ().addOnSuccessListener (new OnSuccessListener <StorageMetadata >() {
159
+ @ Override
160
+ public void onSuccess (final StorageMetadata storageMetadata ) {
161
+ data .putMap ("metadata" , getMetadataAsMap (storageMetadata ));
162
+ callback .invoke (null , data );
163
+ }
164
+ })
165
+ .addOnFailureListener (new OnFailureListener () {
166
+ @ Override
167
+ public void onFailure (@ NonNull Exception exception ) {
168
+ final int errorCode = 1 ;
169
+ WritableMap data = Arguments .createMap ();
170
+ StorageException storageException = StorageException .fromException (exception );
171
+ data .putString ("description" , storageException .getMessage ());
172
+ data .putInt ("code" , errorCode );
173
+ callback .invoke (makeErrorPayload (errorCode , exception ));
174
+ }
175
+ });
176
+ }
177
+ }).addOnFailureListener (new OnFailureListener () {
178
+ @ Override
179
+ public void onFailure (@ NonNull Exception exception ) {
180
+ final int errorCode = 1 ;
181
+ WritableMap data = Arguments .createMap ();
182
+ StorageException storageException = StorageException .fromException (exception );
183
+ data .putString ("description" , storageException .getMessage ());
184
+ data .putInt ("code" , errorCode );
185
+ callback .invoke (makeErrorPayload (errorCode , exception ));
186
+ }
187
+ });
188
+ }
189
+
63
190
@ ReactMethod
64
191
public void downloadUrl (final String javascriptStorageBucket ,
65
192
final String path ,
66
193
final Callback callback ) {
67
194
FirebaseStorage storage = FirebaseStorage .getInstance ();
68
195
String storageBucket = storage .getApp ().getOptions ().getStorageBucket ();
69
196
String storageUrl = "gs://" + storageBucket ;
70
- Log .d (TAG , "FirestackStorage url " + storageUrl + path );
197
+ Log .d (TAG , "Storage url " + storageUrl + path );
71
198
final StorageReference storageRef = storage .getReferenceFromUrl (storageUrl );
72
199
final StorageReference fileRef = storageRef .child (path );
73
200
@@ -90,16 +217,7 @@ public void onSuccess(Uri uri) {
90
217
public void onSuccess (final StorageMetadata storageMetadata ) {
91
218
Log .d (TAG , "getMetadata success " + storageMetadata );
92
219
93
- WritableMap metadata = Arguments .createMap ();
94
- metadata .putString ("getBucket" , storageMetadata .getBucket ());
95
- metadata .putString ("getName" , storageMetadata .getName ());
96
- metadata .putDouble ("sizeBytes" , storageMetadata .getSizeBytes ());
97
- metadata .putDouble ("created_at" , storageMetadata .getCreationTimeMillis ());
98
- metadata .putDouble ("updated_at" , storageMetadata .getUpdatedTimeMillis ());
99
- metadata .putString ("md5hash" , storageMetadata .getMd5Hash ());
100
- metadata .putString ("encoding" , storageMetadata .getContentEncoding ());
101
-
102
- res .putMap ("metadata" , metadata );
220
+ res .putMap ("metadata" , getMetadataAsMap (storageMetadata ));
103
221
res .putString ("name" , storageMetadata .getName ());
104
222
res .putString ("url" , storageMetadata .getDownloadUrl ().toString ());
105
223
callback .invoke (null , res );
@@ -109,7 +227,8 @@ public void onSuccess(final StorageMetadata storageMetadata) {
109
227
@ Override
110
228
public void onFailure (@ NonNull Exception exception ) {
111
229
Log .e (TAG , "Failure in download " + exception );
112
- callback .invoke (makeErrorPayload (1 , exception ));
230
+ final int errorCode = 1 ;
231
+ callback .invoke (makeErrorPayload (errorCode , exception ));
113
232
}
114
233
});
115
234
@@ -129,6 +248,18 @@ public void onFailure(@NonNull Exception exception) {
129
248
});
130
249
}
131
250
251
+ private WritableMap getMetadataAsMap (StorageMetadata storageMetadata ) {
252
+ WritableMap metadata = Arguments .createMap ();
253
+ metadata .putString ("getBucket" , storageMetadata .getBucket ());
254
+ metadata .putString ("getName" , storageMetadata .getName ());
255
+ metadata .putDouble ("sizeBytes" , storageMetadata .getSizeBytes ());
256
+ metadata .putDouble ("created_at" , storageMetadata .getCreationTimeMillis ());
257
+ metadata .putDouble ("updated_at" , storageMetadata .getUpdatedTimeMillis ());
258
+ metadata .putString ("md5hash" , storageMetadata .getMd5Hash ());
259
+ metadata .putString ("encoding" , storageMetadata .getContentEncoding ());
260
+ return metadata ;
261
+ }
262
+
132
263
// STORAGE
133
264
@ ReactMethod
134
265
public void uploadFile (final String urlStr , final String name , final String filepath , final ReadableMap metadata , final Callback callback ) {
@@ -191,9 +322,9 @@ public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
191
322
192
323
if (progress >= 0 ) {
193
324
WritableMap data = Arguments .createMap ();
194
- data .putString ("eventName" , "upload_progress" );
325
+ data .putString ("eventName" , STORAGE_UPLOAD_PROGRESS );
195
326
data .putDouble ("progress" , progress );
196
- Utils .sendEvent (getReactApplicationContext (), "upload_progress" , data );
327
+ Utils .sendEvent (getReactApplicationContext (), STORAGE_UPLOAD_PROGRESS , data );
197
328
}
198
329
}
199
330
})
@@ -204,13 +335,14 @@ public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
204
335
StorageMetadata d = taskSnapshot .getMetadata ();
205
336
String bucket = d .getBucket ();
206
337
WritableMap data = Arguments .createMap ();
207
- data .putString ("eventName" , "upload_paused" );
338
+ data .putString ("eventName" , STORAGE_UPLOAD_PAUSED );
208
339
data .putString ("ref" , bucket );
209
- Utils .sendEvent (getReactApplicationContext (), "upload_paused" , data );
340
+ Utils .sendEvent (getReactApplicationContext (), STORAGE_UPLOAD_PAUSED , data );
210
341
}
211
342
});
212
343
} catch (Exception ex ) {
213
- callback .invoke (makeErrorPayload (2 , ex ));
344
+ final int errorCode = 2 ;
345
+ callback .invoke (makeErrorPayload (errorCode , ex ));
214
346
}
215
347
}
216
348
@@ -221,7 +353,8 @@ public void getRealPathFromURI(final String uri, final Callback callback) {
221
353
callback .invoke (null , path );
222
354
} catch (Exception ex ) {
223
355
ex .printStackTrace ();
224
- callback .invoke (makeErrorPayload (1 , ex ));
356
+ final int errorCode = 1 ;
357
+ callback .invoke (makeErrorPayload (errorCode , ex ));
225
358
}
226
359
}
227
360
0 commit comments