react-native-blob-util 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +100 -0
  2. package/android/src/main/AndroidManifest.xml +0 -3
  3. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java +11 -12
  4. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilBody.java +30 -6
  5. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java +2 -0
  6. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFS.java +94 -3
  7. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java +10 -0
  8. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilMediaCollection.java +123 -87
  9. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +99 -1
  10. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilUtils.java +5 -17
  11. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java +4 -0
  12. package/class/ReactNativeBlobUtilBlobResponse.js +1 -1
  13. package/fs.js +42 -3
  14. package/index.d.ts +30 -1
  15. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.m +4 -3
  16. package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +6 -2
  17. package/ios/ReactNativeBlobUtilConst.h +1 -0
  18. package/ios/ReactNativeBlobUtilConst.m +1 -0
  19. package/ios/ReactNativeBlobUtilFS.h +2 -1
  20. package/ios/ReactNativeBlobUtilFS.m +30 -2
  21. package/ios/ReactNativeBlobUtilFileTransformer.h +24 -0
  22. package/ios/ReactNativeBlobUtilFileTransformer.m +21 -0
  23. package/ios/ReactNativeBlobUtilReqBuilder.m +3 -4
  24. package/ios/ReactNativeBlobUtilRequest.m +35 -7
  25. package/mediacollection.js +6 -1
  26. package/package.json +1 -1
  27. package/polyfill/Fetch.js +4 -2
  28. package/types.js +1 -0
  29. package/ios/IOS7Polyfill.h +0 -27
package/README.md CHANGED
@@ -303,6 +303,26 @@ ReactNativeBlobUtil
303
303
 
304
304
  **These files won't be removed automatically, please refer to [Cache File Management](#user-content-cache-file-management)**
305
305
 
306
+ **Use File Transformer**
307
+
308
+ If you need to perform any processing on the bytes prior to it being written into storage (e.g. if you want it to be encrypted) then you can use `transform` option. NOTE: you will need to set a transformer on the libray (see [Setting a File Transformer](#Setting-A-File-Transformer))
309
+
310
+ ```js
311
+ ReactNativeBlobUtil
312
+ .config({
313
+ // response data will be saved to this path if it has access right.
314
+ path: dirs.DocumentDir + '/path-to-file.anything',
315
+ transform: true
316
+ })
317
+ .fetch('GET', 'http://www.example.com/file/example.zip', {
318
+ //some headers ..
319
+ })
320
+ .then((res) => {
321
+ // the path should be dirs.DocumentDir + 'path-to-file.anything'
322
+ console.log('The file saved to ', res.path())
323
+ })
324
+ ```
325
+
306
326
  #### Upload example : Dropbox [files-upload](https://www.dropbox.com/developers/documentation/http/documentation#files-upload) API
307
327
 
308
328
  `react-native-blob-util` will convert the base64 string in `body` to binary format using native API, this process is done in a separated thread so that it won't block your GUI.
@@ -676,6 +696,14 @@ await ReactNativeBlobUtil.MediaCollection.writeToMediafile('content://....', //
676
696
  );
677
697
  ````
678
698
 
699
+ Copies and tranforms data from a file in the apps storage to an existing entry of the Media Store. NOTE: you must set a transformer on the file in order for the transformation to happen (see [Setting a File Transformer](#Setting-A-File-Transformer)).
700
+
701
+ ````js
702
+ await ReactNativeBlobUtil.MediaCollection.writeToMediafileWithTransform('content://....', // content uri of the entry in the media storage
703
+ localpath // path to the file that should be copied
704
+ );
705
+ ````
706
+
679
707
  #### copyToInternal
680
708
  Copies an entry form the media storage to the apps internal storage.
681
709
  ````js
@@ -697,8 +725,10 @@ File Access APIs
697
725
  - [dirs](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#dirs)
698
726
  - [createFile](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#createfilepath-data-encodingpromise)
699
727
  - [writeFile (0.6.0)](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#writefilepathstring-contentstring--array-encodingstring-appendbooleanpromise)
728
+ - writeFileWithTransform
700
729
  - [appendFile (0.6.0) ](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#appendfilepathstring-contentstring--arraynumber-encodingstring-promisenumber)
701
730
  - [readFile (0.6.0)](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#readfilepath-encodingpromise)
731
+ - readFileWithTransform
702
732
  - [readStream](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#readstreampath-encoding-buffersize-interval-promisernfbreadstream)
703
733
  - [hash (0.10.9)](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#hashpath-algorithm-promise)
704
734
  - [writeStream](https://github.com/RonRadtke/react-native-blob-util/wiki/File-System-Access-API#writestreampathstring-encodingstringpromise)
@@ -878,6 +908,30 @@ ReactNativeBlobUtil.fetch('POST', 'http://example.com/upload', {'Transfer-Encodi
878
908
  ### Self-Signed SSL Server
879
909
 
880
910
  By default, react-native-blob-util does NOT allow connection to unknown certification provider since it's dangerous. To connect a server with self-signed certification, you need to add `trusty` to `config` explicitly. This function is available for version >= `0.5.3`
911
+ In addition since ``0.16.0`` you'll have to define your own trust manager for android.
912
+ ````java
913
+ public class MainApplication extends Application implements ReactApplication {
914
+ ...
915
+ @Override
916
+ public void onCreate() {
917
+ ...
918
+ ReactNativeBlobUtilUtils.sharedTrustManager = final X509TrustManager x509TrustManager = new X509TrustManager() {
919
+ @Override
920
+ public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
921
+ }
922
+
923
+ @Override
924
+ public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
925
+ }
926
+
927
+ @Override
928
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
929
+ return new java.security.cert.X509Certificate[]{};
930
+ }
931
+ };
932
+ ...
933
+ }
934
+ ````
881
935
 
882
936
  ```js
883
937
  ReactNativeBlobUtil.config({
@@ -903,6 +957,10 @@ ReactNativeBlobUtil.config({
903
957
  })
904
958
  ```
905
959
 
960
+ ### Transform Files
961
+
962
+ Sometimes you may need the files to be transformed after reading from storage or before writing into storage (eg encryption/decyrption). In order to perform the transformations, use `readFileWithTransform` and `writeFileWithTransform`. NOTE: you must set a transformer on the file in order for the transformation to happen (see [Setting a File Transformer](#Setting-A-File-Transformer)).
963
+
906
964
  ## Web API Polyfills
907
965
 
908
966
  After `0.8.0` we've made some [Web API polyfills](https://github.com/RonRadtke/react-native-blob-util/wiki/Web-API-Polyfills-(experimental)) that makes some browser-based library available in RN.
@@ -910,6 +968,48 @@ After `0.8.0` we've made some [Web API polyfills](https://github.com/RonRadtke/r
910
968
  - Blob
911
969
  - XMLHttpRequest (Use our implementation if you're going to use it with Blob)
912
970
 
971
+
972
+ ## Setting A File Transformer
973
+
974
+ Setting a file transformer will allow you to specify how data should be transformed whenever the library is writing into storage or reading from storage. A use case for this is if you want the files handled by this library to be encrypted.
975
+
976
+ If you want to use a file transformer, you must implement an interface defined in:
977
+
978
+ [ReactNativeBlobUtilFileTransformer.h (iOS)](/ios/ReactNativeBlobUtilFileTransformer.h)
979
+
980
+ [ReactNativeBlobUtilFileTransformer.java (Android)](/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java)
981
+
982
+ Then you set the File Transformer during app startup
983
+
984
+ Android:
985
+ ```java
986
+ public class MainApplication extends Application implements ReactApplication {
987
+ ...
988
+ @Override
989
+ public void onCreate() {
990
+ ...
991
+ ReactNativeBlobUtilFileTransformer.sharedFileTransformer = new MyCustomEncryptor();
992
+ ...
993
+ }
994
+ ```
995
+
996
+ iOS:
997
+ ```m
998
+ @implementation AppDelegate
999
+ ...
1000
+ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1001
+ {
1002
+ ...
1003
+ [ReactNativeBlobUtilFileTransformer setFileTransformer: MyCustomEncryptor.new];
1004
+ ...
1005
+ }
1006
+ ```
1007
+
1008
+ Here are the places where the transformer would apply
1009
+ - Reading a file from the file system
1010
+ - Writing a file into the file system
1011
+ - Http response is downloaded to storage directly
1012
+
913
1013
  ## Performance Tips
914
1014
 
915
1015
  **Read Stream and Progress Event Overhead**
@@ -1,9 +1,6 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
2
  package="com.ReactNativeBlobUtil">
3
3
 
4
- <!-- Required to access Google Play Licensing -->
5
- <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
6
-
7
4
  <!-- Required to download files from Google Play -->
8
5
  <uses-permission android:name="android.permission.INTERNET" />
9
6
 
@@ -233,11 +233,11 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
233
233
  }
234
234
 
235
235
  @ReactMethod
236
- public void readFile(final String path, final String encoding, final Promise promise) {
236
+ public void readFile(final String path, final String encoding, final boolean transformFile, final Promise promise) {
237
237
  threadPool.execute(new Runnable() {
238
238
  @Override
239
239
  public void run() {
240
- ReactNativeBlobUtilFS.readFile(path, encoding, promise);
240
+ ReactNativeBlobUtilFS.readFile(path, encoding, transformFile, promise);
241
241
  }
242
242
  });
243
243
  }
@@ -253,11 +253,11 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
253
253
  }
254
254
 
255
255
  @ReactMethod
256
- public void writeFile(final String path, final String encoding, final String data, final boolean append, final Promise promise) {
256
+ public void writeFile(final String path, final String encoding, final String data, final boolean transformFile, final boolean append, final Promise promise) {
257
257
  threadPool.execute(new Runnable() {
258
258
  @Override
259
259
  public void run() {
260
- ReactNativeBlobUtilFS.writeFile(path, encoding, data, append, promise);
260
+ ReactNativeBlobUtilFS.writeFile(path, encoding, data, transformFile, append, promise);
261
261
  }
262
262
  });
263
263
  }
@@ -432,29 +432,29 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
432
432
  if (mt == null) promise.reject("ReactNativeBlobUtil.createMediaFile", "invalid mediatype");
433
433
 
434
434
  FileDescription file = new FileDescription(filedata.getString("name"), filedata.getString("mimeType"), filedata.getString("parentFolder"));
435
- Uri res = ReactNativeBlobUtilMediaCollection.createNewMediaFile(file, ReactNativeBlobUtilMediaCollection.MediaType.valueOf(mt));
435
+ Uri res = ReactNativeBlobUtilMediaCollection.createNewMediaFile(file, ReactNativeBlobUtilMediaCollection.MediaType.valueOf(mt), this.getReactApplicationContext());
436
436
  if (res != null) promise.resolve(res.toString());
437
437
  else promise.reject("ReactNativeBlobUtil.createMediaFile", "File could not be created");
438
438
  }
439
439
 
440
- @RequiresApi(api = Build.VERSION_CODES.Q)
441
440
  @ReactMethod
442
- public void writeToMediaFile(String fileUri, String path, Promise promise) {
443
- boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(Uri.parse(fileUri), path, promise);
441
+ public void writeToMediaFile(String fileUri, String path, boolean transformFile, Promise promise) {
442
+ boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(Uri.parse(fileUri), path, transformFile, promise);
444
443
  if(res) promise.resolve("Success");
445
444
  }
446
445
 
446
+ @RequiresApi(api = Build.VERSION_CODES.Q)
447
447
  @ReactMethod
448
448
  public void copyToInternal(String contentUri, String destpath, Promise promise) {
449
449
  ReactNativeBlobUtilMediaCollection.copyToInternal(Uri.parse(contentUri), destpath, promise);
450
450
  }
451
451
 
452
+ @RequiresApi(api = Build.VERSION_CODES.Q)
452
453
  @ReactMethod
453
454
  public void getBlob(String contentUri, String encoding, Promise promise) {
454
455
  ReactNativeBlobUtilMediaCollection.getBlob(Uri.parse(contentUri), encoding, promise);
455
456
  }
456
457
 
457
- @RequiresApi(api = Build.VERSION_CODES.Q)
458
458
  @ReactMethod
459
459
  public void copyToMediaStore(ReadableMap filedata, String mt, String path, Promise promise) {
460
460
  if (!(filedata.hasKey("name") && filedata.hasKey("parentFolder") && filedata.hasKey("mimeType"))) {
@@ -471,15 +471,14 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
471
471
  }
472
472
 
473
473
  FileDescription file = new FileDescription(filedata.getString("name"), filedata.getString("mimeType"), filedata.getString("parentFolder"));
474
- Uri fileuri = ReactNativeBlobUtilMediaCollection.createNewMediaFile(file, ReactNativeBlobUtilMediaCollection.MediaType.valueOf(mt));
474
+ Uri fileuri = ReactNativeBlobUtilMediaCollection.createNewMediaFile(file, ReactNativeBlobUtilMediaCollection.MediaType.valueOf(mt), this.getReactApplicationContext());
475
475
 
476
476
  if (fileuri == null) {
477
477
  promise.reject("ReactNativeBlobUtil.createMediaFile", "File could not be created");
478
478
  return;
479
479
  }
480
480
 
481
- boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(fileuri, path, promise);
482
-
481
+ boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(fileuri, path, false, promise);
483
482
  if(res) promise.resolve(fileuri.toString());
484
483
  }
485
484
 
@@ -26,7 +26,6 @@ import okio.BufferedSink;
26
26
 
27
27
  class ReactNativeBlobUtilBody extends RequestBody {
28
28
 
29
- private InputStream requestStream;
30
29
  private long contentLength = 0;
31
30
  private ReadableArray form;
32
31
  private String mTaskId;
@@ -71,12 +70,10 @@ class ReactNativeBlobUtilBody extends RequestBody {
71
70
  try {
72
71
  switch (requestType) {
73
72
  case SingleFile:
74
- requestStream = getRequestStream();
75
- contentLength = requestStream.available();
73
+ contentLength = getRequestStream().available();
76
74
  break;
77
75
  case AsIs:
78
76
  contentLength = this.rawBody.getBytes().length;
79
- requestStream = new ByteArrayInputStream(this.rawBody.getBytes());
80
77
  break;
81
78
  case Others:
82
79
  break;
@@ -98,7 +95,6 @@ class ReactNativeBlobUtilBody extends RequestBody {
98
95
  this.form = body;
99
96
  try {
100
97
  bodyCache = createMultipartBodyCache();
101
- requestStream = new FileInputStream(bodyCache);
102
98
  contentLength = bodyCache.length();
103
99
  } catch (Exception ex) {
104
100
  ex.printStackTrace();
@@ -107,6 +103,34 @@ class ReactNativeBlobUtilBody extends RequestBody {
107
103
  return this;
108
104
  }
109
105
 
106
+ // This organizes the input stream initialization logic into a method. This allows:
107
+ // 1) Initialization to be deferred until it's needed (when we are ready to pipe it into the BufferedSink)
108
+ // 2) The stream to be initialized and used as many times as necessary. When okhttp runs into
109
+ // a connection error, it will retry the request which will require a new stream to write into
110
+ // the sink once again.
111
+ InputStream getInputStreamForRequestBody() {
112
+ try {
113
+ if (this.form != null) {
114
+ return new FileInputStream(bodyCache);
115
+ } else {
116
+ switch (requestType) {
117
+ case SingleFile:
118
+ return getRequestStream();
119
+ case AsIs:
120
+ return new ByteArrayInputStream(this.rawBody.getBytes());
121
+ case Others:
122
+ ReactNativeBlobUtilUtils.emitWarningEvent("ReactNativeBlobUtil could not create input stream for request type others");
123
+ break;
124
+ }
125
+ }
126
+ } catch (Exception ex){
127
+ ex.printStackTrace();
128
+ ReactNativeBlobUtilUtils.emitWarningEvent("ReactNativeBlobUtil failed to create input stream for request:" + ex.getLocalizedMessage());
129
+ }
130
+
131
+ return null;
132
+ }
133
+
110
134
  @Override
111
135
  public long contentLength() {
112
136
  return chunkedEncoding ? -1 : contentLength;
@@ -120,7 +144,7 @@ class ReactNativeBlobUtilBody extends RequestBody {
120
144
  @Override
121
145
  public void writeTo(@NonNull BufferedSink sink) {
122
146
  try {
123
- pipeStreamToSink(requestStream, sink);
147
+ pipeStreamToSink(getInputStreamForRequestBody(), sink);
124
148
  } catch (Exception ex) {
125
149
  ReactNativeBlobUtilUtils.emitWarningEvent(ex.getLocalizedMessage());
126
150
  ex.printStackTrace();
@@ -8,6 +8,7 @@ import java.util.Locale;
8
8
  class ReactNativeBlobUtilConfig {
9
9
 
10
10
  public Boolean fileCache;
11
+ public Boolean transformFile;
11
12
  public String path;
12
13
  public String appendExt;
13
14
  public ReadableMap addAndroidDownloads;
@@ -26,6 +27,7 @@ class ReactNativeBlobUtilConfig {
26
27
  if (options == null)
27
28
  return;
28
29
  this.fileCache = options.hasKey("fileCache") && options.getBoolean("fileCache");
30
+ this.transformFile = options.hasKey("transformFile") ? options.getBoolean("transformFile") : false;
29
31
  this.path = options.hasKey("path") ? options.getString("path") : null;
30
32
  this.appendExt = options.hasKey("appendExt") ? options.getString("appendExt") : "";
31
33
  this.trusty = options.hasKey("trusty") && options.getBoolean("trusty");
@@ -44,6 +44,76 @@ class ReactNativeBlobUtilFS {
44
44
  this.emitter = ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
45
45
  }
46
46
 
47
+ /**
48
+ * Write string with encoding to file (used for mediastore)
49
+ *
50
+ * @param path Destination file path.
51
+ * @param encoding Encoding of the string.
52
+ * @param data Array passed from JS context.
53
+ */
54
+ static boolean writeFile(String path, String encoding, String data, final boolean append) {
55
+ try {
56
+ int written;
57
+ path = ReactNativeBlobUtilUtils.normalizePath(path);
58
+ File f = new File(path);
59
+ File dir = f.getParentFile();
60
+ if (!f.exists()) {
61
+ if (dir != null && !dir.exists()) {
62
+ if (!dir.mkdirs() && !dir.exists()) {
63
+ return false;
64
+ }
65
+ }
66
+ if (!f.createNewFile()) {
67
+ return false;
68
+ }
69
+ }
70
+
71
+ // write data from a file
72
+ if (encoding.equalsIgnoreCase(ReactNativeBlobUtilConst.DATA_ENCODE_URI)) {
73
+ String normalizedData = ReactNativeBlobUtilUtils.normalizePath(data);
74
+ File src = new File(normalizedData);
75
+ if (!src.exists()) {
76
+ return false;
77
+ }
78
+ byte[] buffer = new byte[10240];
79
+ int read;
80
+ written = 0;
81
+ FileInputStream fin = null;
82
+ FileOutputStream fout = null;
83
+ try {
84
+ fin = new FileInputStream(src);
85
+ fout = new FileOutputStream(f, append);
86
+ while ((read = fin.read(buffer)) > 0) {
87
+ fout.write(buffer, 0, read);
88
+ written += read;
89
+ }
90
+ } finally {
91
+ if (fin != null) {
92
+ fin.close();
93
+ }
94
+ if (fout != null) {
95
+ fout.close();
96
+ }
97
+ }
98
+ } else {
99
+ byte[] bytes = ReactNativeBlobUtilUtils.stringToBytes(data, encoding);
100
+ FileOutputStream fout = new FileOutputStream(f, append);
101
+ try {
102
+ fout.write(bytes);
103
+ written = bytes.length;
104
+ } finally {
105
+ fout.close();
106
+ }
107
+ }
108
+ return true;
109
+ } catch (FileNotFoundException e) {
110
+ // According to https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
111
+ return false;
112
+ } catch (Exception e) {
113
+ return false;
114
+ }
115
+ }
116
+
47
117
  /**
48
118
  * Write string with encoding to file
49
119
  *
@@ -52,12 +122,11 @@ class ReactNativeBlobUtilFS {
52
122
  * @param data Array passed from JS context.
53
123
  * @param promise RCT Promise
54
124
  */
55
- static void writeFile(String path, String encoding, String data, final boolean append, final Promise promise) {
125
+ static void writeFile(String path, String encoding, String data, final boolean transformFile, final boolean append, final Promise promise) {
56
126
  try {
57
127
  int written;
58
128
  File f = new File(path);
59
129
  File dir = f.getParentFile();
60
-
61
130
  if (!f.exists()) {
62
131
  if (dir != null && !dir.exists()) {
63
132
  if (!dir.mkdirs() && !dir.exists()) {
@@ -101,6 +170,12 @@ class ReactNativeBlobUtilFS {
101
170
  }
102
171
  } else {
103
172
  byte[] bytes = ReactNativeBlobUtilUtils.stringToBytes(data, encoding);
173
+ if (transformFile) {
174
+ if (ReactNativeBlobUtilFileTransformer.sharedFileTransformer == null) {
175
+ throw new IllegalStateException("Write file with transform was specified but the shared file transformer is not set");
176
+ }
177
+ bytes = ReactNativeBlobUtilFileTransformer.sharedFileTransformer.onWriteFile(bytes);
178
+ }
104
179
  FileOutputStream fout = new FileOutputStream(f, append);
105
180
  try {
106
181
  fout.write(bytes);
@@ -169,7 +244,7 @@ class ReactNativeBlobUtilFS {
169
244
  * @param encoding Encoding of read stream.
170
245
  * @param promise JS promise
171
246
  */
172
- static void readFile(String path, String encoding, final Promise promise) {
247
+ static void readFile(String path, String encoding, final boolean transformFile, final Promise promise) {
173
248
  String resolved = ReactNativeBlobUtilUtils.normalizePath(path);
174
249
  if (resolved != null)
175
250
  path = resolved;
@@ -212,6 +287,13 @@ class ReactNativeBlobUtilFS {
212
287
  return;
213
288
  }
214
289
 
290
+ if (transformFile) {
291
+ if (ReactNativeBlobUtilFileTransformer.sharedFileTransformer == null) {
292
+ throw new IllegalStateException("Read file with transform was specified but the shared file transformer is not set");
293
+ }
294
+ bytes = ReactNativeBlobUtilFileTransformer.sharedFileTransformer.onReadFile(bytes);
295
+ }
296
+
215
297
  switch (encoding.toLowerCase(Locale.ROOT)) {
216
298
  case "base64":
217
299
  promise.resolve(Base64.encodeToString(bytes, Base64.NO_WRAP));
@@ -373,6 +455,7 @@ class ReactNativeBlobUtilFS {
373
455
  * @param promise JS promise
374
456
  */
375
457
  static void mkdir(String path, Promise promise) {
458
+ path = ReactNativeBlobUtilUtils.normalizePath(path);
376
459
  File dest = new File(path);
377
460
  if (dest.exists()) {
378
461
  promise.reject("EEXIST", (dest.isDirectory() ? "Folder" : "File") + " '" + path + "' already exists");
@@ -400,6 +483,7 @@ class ReactNativeBlobUtilFS {
400
483
  */
401
484
  static void cp(String path, String dest, Callback callback) {
402
485
  path = ReactNativeBlobUtilUtils.normalizePath(path);
486
+ dest = ReactNativeBlobUtilUtils.normalizePath(dest);
403
487
  InputStream in = null;
404
488
  OutputStream out = null;
405
489
  String message = "";
@@ -456,6 +540,8 @@ class ReactNativeBlobUtilFS {
456
540
  * @param callback JS context callback
457
541
  */
458
542
  static void mv(String path, String dest, Callback callback) {
543
+ path = ReactNativeBlobUtilUtils.normalizePath(path);
544
+ dest = ReactNativeBlobUtilUtils.normalizePath(dest);
459
545
  File src = new File(path);
460
546
  if (!src.exists()) {
461
547
  callback.invoke("Source file at path `" + path + "` does not exist");
@@ -559,6 +645,7 @@ class ReactNativeBlobUtilFS {
559
645
  static void slice(String path, String dest, int start, int end, String encode, Promise promise) {
560
646
  try {
561
647
  path = ReactNativeBlobUtilUtils.normalizePath(path);
648
+ dest = ReactNativeBlobUtilUtils.normalizePath(dest);
562
649
  File source = new File(path);
563
650
  if (source.isDirectory()) {
564
651
  promise.reject("EISDIR", "Expecting a file but '" + path + "' is a directory");
@@ -722,6 +809,8 @@ class ReactNativeBlobUtilFS {
722
809
  promise.reject("EINVAL", "Invalid algorithm '" + algorithm + "', must be one of md5, sha1, sha224, sha256, sha384, sha512");
723
810
  return;
724
811
  }
812
+
813
+ path = ReactNativeBlobUtilUtils.normalizePath(path);
725
814
 
726
815
  File file = new File(path);
727
816
 
@@ -769,6 +858,7 @@ class ReactNativeBlobUtilFS {
769
858
  */
770
859
  static void createFile(String path, String data, String encoding, Promise promise) {
771
860
  try {
861
+ path = ReactNativeBlobUtilUtils.normalizePath(path);
772
862
  File dest = new File(path);
773
863
  boolean created = dest.createNewFile();
774
864
  if (encoding.equals(ReactNativeBlobUtilConst.DATA_ENCODE_URI)) {
@@ -811,6 +901,7 @@ class ReactNativeBlobUtilFS {
811
901
  */
812
902
  static void createFileASCII(String path, ReadableArray data, Promise promise) {
813
903
  try {
904
+ path = ReactNativeBlobUtilUtils.normalizePath(path);
814
905
  File dest = new File(path);
815
906
  boolean created = dest.createNewFile();
816
907
  if (!created) {
@@ -0,0 +1,10 @@
1
+ package com.ReactNativeBlobUtil;
2
+
3
+ public class ReactNativeBlobUtilFileTransformer {
4
+ public interface FileTransformer {
5
+ public byte[] onWriteFile(byte[] data);
6
+ public byte[] onReadFile(byte[] data);
7
+ }
8
+
9
+ public static ReactNativeBlobUtilFileTransformer.FileTransformer sharedFileTransformer;
10
+ }