react-native-blob-util 0.14.1 → 0.15.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.
- package/README.md +76 -0
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java +7 -7
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java +2 -0
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFS.java +25 -2
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java +10 -0
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilMediaCollection.java +20 -5
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +29 -1
- package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java +4 -0
- package/class/ReactNativeBlobUtilBlobResponse.js +1 -1
- package/fs.js +42 -3
- package/index.d.ts +29 -0
- package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.m +4 -3
- package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +6 -0
- package/ios/ReactNativeBlobUtilConst.h +1 -0
- package/ios/ReactNativeBlobUtilConst.m +1 -0
- package/ios/ReactNativeBlobUtilFS.h +2 -1
- package/ios/ReactNativeBlobUtilFS.m +29 -0
- package/ios/ReactNativeBlobUtilFileTransformer.h +24 -0
- package/ios/ReactNativeBlobUtilFileTransformer.m +21 -0
- package/ios/ReactNativeBlobUtilReqBuilder.m +2 -2
- package/ios/ReactNativeBlobUtilRequest.m +30 -1
- package/mediacollection.js +6 -1
- package/package.json +1 -1
- package/polyfill/Fetch.js +4 -2
- package/types.js +1 -0
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)
|
|
@@ -903,6 +933,10 @@ ReactNativeBlobUtil.config({
|
|
|
903
933
|
})
|
|
904
934
|
```
|
|
905
935
|
|
|
936
|
+
### Transform Files
|
|
937
|
+
|
|
938
|
+
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)).
|
|
939
|
+
|
|
906
940
|
## Web API Polyfills
|
|
907
941
|
|
|
908
942
|
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 +944,48 @@ After `0.8.0` we've made some [Web API polyfills](https://github.com/RonRadtke/r
|
|
|
910
944
|
- Blob
|
|
911
945
|
- XMLHttpRequest (Use our implementation if you're going to use it with Blob)
|
|
912
946
|
|
|
947
|
+
|
|
948
|
+
## Setting A File Transformer
|
|
949
|
+
|
|
950
|
+
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.
|
|
951
|
+
|
|
952
|
+
If you want to use a file transformer, you must implement an interface defined in:
|
|
953
|
+
|
|
954
|
+
[ReactNativeBlobUtilFileTransformer.h (iOS)](/ios/ReactNativeBlobUtilFileTransformer.h)
|
|
955
|
+
|
|
956
|
+
[ReactNativeBlobUtilFileTransformer.java (Android)](/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java)
|
|
957
|
+
|
|
958
|
+
Then you set the File Transformer during app startup
|
|
959
|
+
|
|
960
|
+
Android:
|
|
961
|
+
```java
|
|
962
|
+
public class MainApplication extends Application implements ReactApplication {
|
|
963
|
+
...
|
|
964
|
+
@Override
|
|
965
|
+
public void onCreate() {
|
|
966
|
+
...
|
|
967
|
+
ReactNativeBlobUtilFileTransformer.sharedFileTransformer = new MyCustomEncryptor();
|
|
968
|
+
...
|
|
969
|
+
}
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
iOS:
|
|
973
|
+
```m
|
|
974
|
+
@implementation AppDelegate
|
|
975
|
+
...
|
|
976
|
+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
|
977
|
+
{
|
|
978
|
+
...
|
|
979
|
+
[ReactNativeBlobUtilFileTransformer setFileTransformer: MyCustomEncryptor.new];
|
|
980
|
+
...
|
|
981
|
+
}
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
Here are the places where the transformer would apply
|
|
985
|
+
- Reading a file from the file system
|
|
986
|
+
- Writing a file into the file system
|
|
987
|
+
- Http response is downloaded to storage directly
|
|
988
|
+
|
|
913
989
|
## Performance Tips
|
|
914
990
|
|
|
915
991
|
**Read Stream and Progress Event Overhead**
|
|
@@ -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
|
}
|
|
@@ -438,8 +438,8 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
@ReactMethod
|
|
441
|
-
public void writeToMediaFile(String fileUri, String path, Promise promise) {
|
|
442
|
-
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);
|
|
443
443
|
if(res) promise.resolve("Success");
|
|
444
444
|
}
|
|
445
445
|
|
|
@@ -478,7 +478,7 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
|
|
|
478
478
|
return;
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
-
boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(fileuri, path, promise);
|
|
481
|
+
boolean res = ReactNativeBlobUtilMediaCollection.writeToMediaFile(fileuri, path, false, promise);
|
|
482
482
|
if(res) promise.resolve(fileuri.toString());
|
|
483
483
|
}
|
|
484
484
|
|
|
@@ -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");
|
|
@@ -54,6 +54,7 @@ class ReactNativeBlobUtilFS {
|
|
|
54
54
|
static boolean writeFile(String path, String encoding, String data, final boolean append) {
|
|
55
55
|
try {
|
|
56
56
|
int written;
|
|
57
|
+
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
57
58
|
File f = new File(path);
|
|
58
59
|
File dir = f.getParentFile();
|
|
59
60
|
if (!f.exists()) {
|
|
@@ -121,7 +122,7 @@ class ReactNativeBlobUtilFS {
|
|
|
121
122
|
* @param data Array passed from JS context.
|
|
122
123
|
* @param promise RCT Promise
|
|
123
124
|
*/
|
|
124
|
-
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) {
|
|
125
126
|
try {
|
|
126
127
|
int written;
|
|
127
128
|
File f = new File(path);
|
|
@@ -169,6 +170,12 @@ class ReactNativeBlobUtilFS {
|
|
|
169
170
|
}
|
|
170
171
|
} else {
|
|
171
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
|
+
}
|
|
172
179
|
FileOutputStream fout = new FileOutputStream(f, append);
|
|
173
180
|
try {
|
|
174
181
|
fout.write(bytes);
|
|
@@ -237,7 +244,7 @@ class ReactNativeBlobUtilFS {
|
|
|
237
244
|
* @param encoding Encoding of read stream.
|
|
238
245
|
* @param promise JS promise
|
|
239
246
|
*/
|
|
240
|
-
static void readFile(String path, String encoding, final Promise promise) {
|
|
247
|
+
static void readFile(String path, String encoding, final boolean transformFile, final Promise promise) {
|
|
241
248
|
String resolved = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
242
249
|
if (resolved != null)
|
|
243
250
|
path = resolved;
|
|
@@ -280,6 +287,13 @@ class ReactNativeBlobUtilFS {
|
|
|
280
287
|
return;
|
|
281
288
|
}
|
|
282
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
|
+
|
|
283
297
|
switch (encoding.toLowerCase(Locale.ROOT)) {
|
|
284
298
|
case "base64":
|
|
285
299
|
promise.resolve(Base64.encodeToString(bytes, Base64.NO_WRAP));
|
|
@@ -441,6 +455,7 @@ class ReactNativeBlobUtilFS {
|
|
|
441
455
|
* @param promise JS promise
|
|
442
456
|
*/
|
|
443
457
|
static void mkdir(String path, Promise promise) {
|
|
458
|
+
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
444
459
|
File dest = new File(path);
|
|
445
460
|
if (dest.exists()) {
|
|
446
461
|
promise.reject("EEXIST", (dest.isDirectory() ? "Folder" : "File") + " '" + path + "' already exists");
|
|
@@ -468,6 +483,7 @@ class ReactNativeBlobUtilFS {
|
|
|
468
483
|
*/
|
|
469
484
|
static void cp(String path, String dest, Callback callback) {
|
|
470
485
|
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
486
|
+
dest = ReactNativeBlobUtilUtils.normalizePath(dest);
|
|
471
487
|
InputStream in = null;
|
|
472
488
|
OutputStream out = null;
|
|
473
489
|
String message = "";
|
|
@@ -524,6 +540,8 @@ class ReactNativeBlobUtilFS {
|
|
|
524
540
|
* @param callback JS context callback
|
|
525
541
|
*/
|
|
526
542
|
static void mv(String path, String dest, Callback callback) {
|
|
543
|
+
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
544
|
+
dest = ReactNativeBlobUtilUtils.normalizePath(dest);
|
|
527
545
|
File src = new File(path);
|
|
528
546
|
if (!src.exists()) {
|
|
529
547
|
callback.invoke("Source file at path `" + path + "` does not exist");
|
|
@@ -627,6 +645,7 @@ class ReactNativeBlobUtilFS {
|
|
|
627
645
|
static void slice(String path, String dest, int start, int end, String encode, Promise promise) {
|
|
628
646
|
try {
|
|
629
647
|
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
648
|
+
dest = ReactNativeBlobUtilUtils.normalizePath(dest);
|
|
630
649
|
File source = new File(path);
|
|
631
650
|
if (source.isDirectory()) {
|
|
632
651
|
promise.reject("EISDIR", "Expecting a file but '" + path + "' is a directory");
|
|
@@ -790,6 +809,8 @@ class ReactNativeBlobUtilFS {
|
|
|
790
809
|
promise.reject("EINVAL", "Invalid algorithm '" + algorithm + "', must be one of md5, sha1, sha224, sha256, sha384, sha512");
|
|
791
810
|
return;
|
|
792
811
|
}
|
|
812
|
+
|
|
813
|
+
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
793
814
|
|
|
794
815
|
File file = new File(path);
|
|
795
816
|
|
|
@@ -837,6 +858,7 @@ class ReactNativeBlobUtilFS {
|
|
|
837
858
|
*/
|
|
838
859
|
static void createFile(String path, String data, String encoding, Promise promise) {
|
|
839
860
|
try {
|
|
861
|
+
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
840
862
|
File dest = new File(path);
|
|
841
863
|
boolean created = dest.createNewFile();
|
|
842
864
|
if (encoding.equals(ReactNativeBlobUtilConst.DATA_ENCODE_URI)) {
|
|
@@ -879,6 +901,7 @@ class ReactNativeBlobUtilFS {
|
|
|
879
901
|
*/
|
|
880
902
|
static void createFileASCII(String path, ReadableArray data, Promise promise) {
|
|
881
903
|
try {
|
|
904
|
+
path = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
882
905
|
File dest = new File(path);
|
|
883
906
|
boolean created = dest.createNewFile();
|
|
884
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
|
+
}
|
package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilMediaCollection.java
CHANGED
|
@@ -124,7 +124,7 @@ public class ReactNativeBlobUtilMediaCollection {
|
|
|
124
124
|
return null;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
public static boolean writeToMediaFile(Uri fileUri, String data, Promise promise) {
|
|
127
|
+
public static boolean writeToMediaFile(Uri fileUri, String data, boolean transformFile, Promise promise) {
|
|
128
128
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
129
129
|
try {
|
|
130
130
|
Context appCtx = ReactNativeBlobUtil.RCTContext.getApplicationContext();
|
|
@@ -151,16 +151,31 @@ public class ReactNativeBlobUtilMediaCollection {
|
|
|
151
151
|
promise.reject("ENOENT", "No such file ('" + normalizedData + "')");
|
|
152
152
|
return false;
|
|
153
153
|
}
|
|
154
|
-
|
|
155
|
-
int read;
|
|
154
|
+
|
|
156
155
|
|
|
157
156
|
FileInputStream fin = new FileInputStream(src);
|
|
158
157
|
FileOutputStream out = new FileOutputStream(descr.getFileDescriptor());
|
|
159
158
|
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
if (transformFile) {
|
|
160
|
+
// in order to transform file, we must load the entire file onto memory
|
|
161
|
+
int length = (int) src.length();
|
|
162
|
+
byte[] bytes = new byte[length];
|
|
163
|
+
fin.read(bytes);
|
|
164
|
+
if (ReactNativeBlobUtilFileTransformer.sharedFileTransformer == null) {
|
|
165
|
+
throw new IllegalStateException("Write to media file with transform was specified but the shared file transformer is not set");
|
|
166
|
+
}
|
|
167
|
+
byte[] transformedBytes = ReactNativeBlobUtilFileTransformer.sharedFileTransformer.onWriteFile(bytes);
|
|
168
|
+
out.write(transformedBytes);
|
|
169
|
+
} else {
|
|
170
|
+
byte[] buf = new byte[10240];
|
|
171
|
+
int read;
|
|
172
|
+
|
|
173
|
+
while ((read = fin.read(buf)) > 0) {
|
|
174
|
+
out.write(buf, 0, read);
|
|
175
|
+
}
|
|
162
176
|
}
|
|
163
177
|
|
|
178
|
+
|
|
164
179
|
fin.close();
|
|
165
180
|
out.close();
|
|
166
181
|
descr.close();
|
|
@@ -87,6 +87,12 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
|
|
|
87
87
|
BASE64
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
private boolean shouldTransformFile() {
|
|
91
|
+
return this.options.transformFile &&
|
|
92
|
+
// Can only process if it's written to a file
|
|
93
|
+
(this.options.fileCache || this.options.path != null);
|
|
94
|
+
}
|
|
95
|
+
|
|
90
96
|
public static HashMap<String, Call> taskTable = new HashMap<>();
|
|
91
97
|
public static HashMap<String, Long> androidDownloadManagerTaskTable = new HashMap<>();
|
|
92
98
|
static HashMap<String, ReactNativeBlobUtilProgressConfig> progressReport = new HashMap<>();
|
|
@@ -124,7 +130,9 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
|
|
|
124
130
|
this.rawRequestBodyArray = arrayBody;
|
|
125
131
|
this.client = client;
|
|
126
132
|
|
|
127
|
-
|
|
133
|
+
// If transformFile is specified, we first want to get the response back in memory so we can
|
|
134
|
+
// encrypt it wholesale and at that point, write it into the file storage.
|
|
135
|
+
if((this.options.fileCache || this.options.path != null) && !this.shouldTransformFile())
|
|
128
136
|
responseType = ResponseType.FileStorage;
|
|
129
137
|
else
|
|
130
138
|
responseType = ResponseType.KeepInMemory;
|
|
@@ -557,6 +565,26 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
|
|
|
557
565
|
// response data directly pass to JS context as string.
|
|
558
566
|
else {
|
|
559
567
|
byte[] b = resp.body().bytes();
|
|
568
|
+
// If process file option is turned on, we first keep response in memory and then stream that content
|
|
569
|
+
// after processing
|
|
570
|
+
if (this.shouldTransformFile()) {
|
|
571
|
+
if (ReactNativeBlobUtilFileTransformer.sharedFileTransformer == null) {
|
|
572
|
+
throw new IllegalStateException("Write file with transform was specified but the shared file transformer is not set");
|
|
573
|
+
}
|
|
574
|
+
this.destPath = this.destPath.replace("?append=true", "");
|
|
575
|
+
File file = new File(this.destPath);
|
|
576
|
+
if (!file.exists()) {
|
|
577
|
+
file.createNewFile();
|
|
578
|
+
}
|
|
579
|
+
try (FileOutputStream fos = new FileOutputStream(file)) {
|
|
580
|
+
fos.write(ReactNativeBlobUtilFileTransformer.sharedFileTransformer.onWriteFile(b));
|
|
581
|
+
} catch(Exception e) {
|
|
582
|
+
callback.invoke("Error from file transformer:" + e.getLocalizedMessage(), null);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
callback.invoke(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, this.destPath);
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
560
588
|
if (responseFormat == ResponseFormat.BASE64) {
|
|
561
589
|
callback.invoke(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_BASE64, android.util.Base64.encodeToString(b, Base64.NO_WRAP));
|
|
562
590
|
return;
|
package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java
CHANGED
|
@@ -72,6 +72,10 @@ public class ReactNativeBlobUtilFileResp extends ResponseBody {
|
|
|
72
72
|
|
|
73
73
|
@Override
|
|
74
74
|
public long contentLength() {
|
|
75
|
+
if (originalBody.contentLength() > Integer.MAX_VALUE) {
|
|
76
|
+
// This is a workaround for a bug Okio buffer where it can't handle larger than int.
|
|
77
|
+
return Integer.MAX_VALUE;
|
|
78
|
+
}
|
|
75
79
|
return originalBody.contentLength();
|
|
76
80
|
}
|
|
77
81
|
|
package/fs.js
CHANGED
|
@@ -160,7 +160,20 @@ function readFile(path: string, encoding: string = 'utf8'): Promise<any> {
|
|
|
160
160
|
if (typeof path !== 'string') {
|
|
161
161
|
return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" ')));
|
|
162
162
|
}
|
|
163
|
-
return ReactNativeBlobUtil.readFile(path, encoding);
|
|
163
|
+
return ReactNativeBlobUtil.readFile(path, encoding, false);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Reads the file, then transforms it before returning the content
|
|
168
|
+
* @param {string} path Path of the file.
|
|
169
|
+
* @param {'base64' | 'utf8' | 'ascii'} encoding Encoding of read stream.
|
|
170
|
+
* @return {Promise<Array<number> | string>}
|
|
171
|
+
*/
|
|
172
|
+
function readFileWithTransform(path: string, encoding: string = 'utf8'): Promise<any> {
|
|
173
|
+
if (typeof path !== 'string') {
|
|
174
|
+
return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" ')))
|
|
175
|
+
}
|
|
176
|
+
return ReactNativeBlobUtil.readFile(path, encoding, true);
|
|
164
177
|
}
|
|
165
178
|
|
|
166
179
|
/**
|
|
@@ -186,7 +199,31 @@ function writeFile(path: string, data: string | Array<number>, encoding: ?string
|
|
|
186
199
|
return Promise.reject(addCode('EINVAL', new TypeError(`"data" must be a String when encoding is "utf8" or "base64", but it is "${typeof data}"`)));
|
|
187
200
|
}
|
|
188
201
|
else
|
|
189
|
-
return ReactNativeBlobUtil.writeFile(path, encoding, data, false);
|
|
202
|
+
return ReactNativeBlobUtil.writeFile(path, encoding, data, false, false);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Transforms the data and then writes to the file.
|
|
208
|
+
* @param {string} path Path of the file.
|
|
209
|
+
* @param {string | number[]} data Data to write to the file.
|
|
210
|
+
* @param {string} encoding Encoding of data (Optional).
|
|
211
|
+
* @return {Promise}
|
|
212
|
+
*/
|
|
213
|
+
function writeFileWithTransform(path: string, data: string | Array<number>, encoding: ?string = 'utf8'): Promise {
|
|
214
|
+
if (typeof path !== 'string') {
|
|
215
|
+
return Promise.reject(addCode('EINVAL', new TypeError('Missing argument "path" ')))
|
|
216
|
+
}
|
|
217
|
+
if (encoding.toLocaleLowerCase() === 'ascii') {
|
|
218
|
+
return Promise.reject(addCode('EINVAL', new TypeError('ascii is not supported for converted files')))
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
if (typeof data !== 'string') {
|
|
222
|
+
return Promise.reject(addCode('EINVAL', new TypeError(`"data" must be a String when encoding is "utf8" or "base64", but it is "${typeof data}"`)))
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
else
|
|
226
|
+
return ReactNativeBlobUtil.writeFile(path, encoding, data, true, false)
|
|
190
227
|
}
|
|
191
228
|
}
|
|
192
229
|
|
|
@@ -206,7 +243,7 @@ function appendFile(path: string, data: string | Array<number>, encoding?: strin
|
|
|
206
243
|
return Promise.reject(addCode('EINVAL'), new TypeError(`"data" must be a String when encoding is "utf8" or "base64", but it is "${typeof data}"`));
|
|
207
244
|
}
|
|
208
245
|
else
|
|
209
|
-
return ReactNativeBlobUtil.writeFile(path, encoding, data, true);
|
|
246
|
+
return ReactNativeBlobUtil.writeFile(path, encoding, data, false, true);
|
|
210
247
|
}
|
|
211
248
|
}
|
|
212
249
|
|
|
@@ -415,6 +452,8 @@ export default {
|
|
|
415
452
|
cp,
|
|
416
453
|
writeStream,
|
|
417
454
|
writeFile,
|
|
455
|
+
writeFileWithTransform,
|
|
456
|
+
readFileWithTransform,
|
|
418
457
|
appendFile,
|
|
419
458
|
pathForAppGroup,
|
|
420
459
|
syncPathAppGroup,
|
package/index.d.ts
CHANGED
|
@@ -399,6 +399,14 @@ export interface FS {
|
|
|
399
399
|
*/
|
|
400
400
|
writeFile(path: string, data: string | number[], encoding?: Encoding): Promise<void>;
|
|
401
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Processes the data and then writes to the file.
|
|
404
|
+
* @param path Path of the file.
|
|
405
|
+
* @param data Data to write to the file.
|
|
406
|
+
* @param encoding Encoding of data (Optional).
|
|
407
|
+
*/
|
|
408
|
+
writeFileWithTransform(path: string, data: string | number[], encoding?: Encoding): Promise<void>;
|
|
409
|
+
|
|
402
410
|
appendFile(path: string, data: string | number[], encoding?: Encoding | "uri"): Promise<number>;
|
|
403
411
|
|
|
404
412
|
/**
|
|
@@ -408,6 +416,13 @@ export interface FS {
|
|
|
408
416
|
*/
|
|
409
417
|
readFile(path: string, encoding: Encoding, bufferSize?: number): Promise<any>;
|
|
410
418
|
|
|
419
|
+
/**
|
|
420
|
+
* Reads from a file and then processes the data before returning
|
|
421
|
+
* @param path Path of the file.
|
|
422
|
+
* @param encoding Encoding of read stream.
|
|
423
|
+
*/
|
|
424
|
+
readFileWithTransform(path: string, encoding: Encoding, bufferSize?: number): Promise<any>;
|
|
425
|
+
|
|
411
426
|
/**
|
|
412
427
|
* Check if file exists and if it is a folder.
|
|
413
428
|
* @param path Path to check
|
|
@@ -698,6 +713,13 @@ export interface ReactNativeBlobUtilConfig {
|
|
|
698
713
|
*/
|
|
699
714
|
fileCache?: boolean;
|
|
700
715
|
|
|
716
|
+
/**
|
|
717
|
+
* Set this property to true if you want the data to be processed before it gets written onto disk.
|
|
718
|
+
* This only has effect if the FileTransformer has been registered and the library is configured to write
|
|
719
|
+
* response onto disk.
|
|
720
|
+
*/
|
|
721
|
+
transformFile?: boolean;
|
|
722
|
+
|
|
701
723
|
/**
|
|
702
724
|
* Set this property to change temp file extension that created by fetch response data.
|
|
703
725
|
*/
|
|
@@ -808,6 +830,13 @@ export interface MediaCollection {
|
|
|
808
830
|
*/
|
|
809
831
|
writeToMediafile(uri: string, path: string): Promise<string>
|
|
810
832
|
|
|
833
|
+
/**
|
|
834
|
+
* Copies and transforms an existing file to a mediastore file. Make sure FileTransformer is set
|
|
835
|
+
* @param uri URI of the destination mediastore file
|
|
836
|
+
* @param path Path to the existing file which should be copied
|
|
837
|
+
*/
|
|
838
|
+
writeToMediafileWithTransform(uri: string, path: string): Promise<string>
|
|
839
|
+
|
|
811
840
|
/**
|
|
812
841
|
* Copies a file from the mediastore to the apps internal storage
|
|
813
842
|
* @param contenturi URI of the mediastore file
|
|
@@ -252,9 +252,9 @@ RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callb
|
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
#pragma mark - fs.writeFile
|
|
255
|
-
RCT_EXPORT_METHOD(writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
255
|
+
RCT_EXPORT_METHOD(writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data transformFile:(BOOL)transformFile append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
256
256
|
{
|
|
257
|
-
[ReactNativeBlobUtilFS writeFile:path encoding:[NSString stringWithString:encoding] data:data append:append resolver:resolve rejecter:reject];
|
|
257
|
+
[ReactNativeBlobUtilFS writeFile:path encoding:[NSString stringWithString:encoding] data:data transformFile:transformFile append:append resolver:resolve rejecter:reject];
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
#pragma mark - fs.writeArray
|
|
@@ -494,11 +494,12 @@ RCT_EXPORT_METHOD(mkdir:(NSString *)path resolver:(RCTPromiseResolveBlock)resolv
|
|
|
494
494
|
#pragma mark - fs.readFile
|
|
495
495
|
RCT_EXPORT_METHOD(readFile:(NSString *)path
|
|
496
496
|
encoding:(NSString *)encoding
|
|
497
|
+
transformFile:(BOOL) transformFile
|
|
497
498
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
498
499
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
499
500
|
{
|
|
500
501
|
|
|
501
|
-
[ReactNativeBlobUtilFS readFile:path encoding:encoding onComplete:^(NSData * content, NSString * code, NSString * err) {
|
|
502
|
+
[ReactNativeBlobUtilFS readFile:path encoding:encoding transformFile:transformFile onComplete:^(NSData * content, NSString * code, NSString * err) {
|
|
502
503
|
if(err != nil) {
|
|
503
504
|
reject(code, err, nil);
|
|
504
505
|
return;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
/* Begin PBXBuildFile section */
|
|
10
10
|
8C4801A6200CF71700FED7ED /* ReactNativeBlobUtilRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C4801A5200CF71700FED7ED /* ReactNativeBlobUtilRequest.m */; };
|
|
11
|
+
9FD8D3C326F1736000009F35 /* ReactNativeBlobUtilFileTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9FD8D3C226F1736000009F35 /* ReactNativeBlobUtilFileTransformer.m */; };
|
|
11
12
|
A158F4271D052E49006FFD38 /* ReactNativeBlobUtilFS.m in Sources */ = {isa = PBXBuildFile; fileRef = A158F4261D052E49006FFD38 /* ReactNativeBlobUtilFS.m */; };
|
|
12
13
|
A158F42D1D0535BB006FFD38 /* ReactNativeBlobUtilConst.m in Sources */ = {isa = PBXBuildFile; fileRef = A158F42C1D0535BB006FFD38 /* ReactNativeBlobUtilConst.m */; };
|
|
13
14
|
A158F4301D0539DB006FFD38 /* ReactNativeBlobUtilNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = A158F42F1D0539DB006FFD38 /* ReactNativeBlobUtilNetwork.m */; };
|
|
@@ -32,6 +33,8 @@
|
|
|
32
33
|
/* Begin PBXFileReference section */
|
|
33
34
|
8C4801A4200CF71700FED7ED /* ReactNativeBlobUtilRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeBlobUtilRequest.h; sourceTree = "<group>"; };
|
|
34
35
|
8C4801A5200CF71700FED7ED /* ReactNativeBlobUtilRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactNativeBlobUtilRequest.m; sourceTree = "<group>"; };
|
|
36
|
+
9FD8D3C126F1709A00009F35 /* ReactNativeBlobUtilFileTransformer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeBlobUtilFileTransformer.h; sourceTree = "<group>"; };
|
|
37
|
+
9FD8D3C226F1736000009F35 /* ReactNativeBlobUtilFileTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactNativeBlobUtilFileTransformer.m; sourceTree = "<group>"; };
|
|
35
38
|
A158F4261D052E49006FFD38 /* ReactNativeBlobUtilFS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReactNativeBlobUtilFS.m; sourceTree = "<group>"; };
|
|
36
39
|
A158F4281D052E57006FFD38 /* ReactNativeBlobUtilFS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeBlobUtilFS.h; sourceTree = "<group>"; };
|
|
37
40
|
A158F4291D0534A9006FFD38 /* ReactNativeBlobUtilConst.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeBlobUtilConst.h; sourceTree = "<group>"; };
|
|
@@ -69,6 +72,8 @@
|
|
|
69
72
|
A15C30051CD25C330074CB35 = {
|
|
70
73
|
isa = PBXGroup;
|
|
71
74
|
children = (
|
|
75
|
+
9FD8D3C226F1736000009F35 /* ReactNativeBlobUtilFileTransformer.m */,
|
|
76
|
+
9FD8D3C126F1709A00009F35 /* ReactNativeBlobUtilFileTransformer.h */,
|
|
72
77
|
A19B48241D98102400E6868A /* ReactNativeBlobUtilProgress.m */,
|
|
73
78
|
A19B48231D98100800E6868A /* ReactNativeBlobUtilProgress.h */,
|
|
74
79
|
A1F950181D7E9134002A95A6 /* IOS7Polyfill.h */,
|
|
@@ -156,6 +161,7 @@
|
|
|
156
161
|
A166D1AA1CE0647A00273590 /* ReactNativeBlobUtil.h in Sources */,
|
|
157
162
|
8C4801A6200CF71700FED7ED /* ReactNativeBlobUtilRequest.m in Sources */,
|
|
158
163
|
A158F42D1D0535BB006FFD38 /* ReactNativeBlobUtilConst.m in Sources */,
|
|
164
|
+
9FD8D3C326F1736000009F35 /* ReactNativeBlobUtilFileTransformer.m in Sources */,
|
|
159
165
|
A158F4271D052E49006FFD38 /* ReactNativeBlobUtilFS.m in Sources */,
|
|
160
166
|
A158F4301D0539DB006FFD38 /* ReactNativeBlobUtilNetwork.m in Sources */,
|
|
161
167
|
A19B48251D98102400E6868A /* ReactNativeBlobUtilProgress.m in Sources */,
|
|
@@ -29,6 +29,7 @@ extern NSString *const AL_PREFIX;
|
|
|
29
29
|
|
|
30
30
|
// config
|
|
31
31
|
extern NSString *const CONFIG_USE_TEMP;
|
|
32
|
+
extern NSString *const CONFIG_TRANSFORM_FILE;
|
|
32
33
|
extern NSString *const CONFIG_FILE_PATH;
|
|
33
34
|
extern NSString *const CONFIG_FILE_EXT;
|
|
34
35
|
extern NSString *const CONFIG_TRUSTY;
|
|
@@ -13,6 +13,7 @@ NSString *const AL_PREFIX = @"assets-library://";
|
|
|
13
13
|
|
|
14
14
|
// fetch configs
|
|
15
15
|
NSString *const CONFIG_USE_TEMP = @"fileCache";
|
|
16
|
+
NSString *const CONFIG_TRANSFORM_FILE = @"transformFile";
|
|
16
17
|
NSString *const CONFIG_FILE_PATH = @"path";
|
|
17
18
|
NSString *const CONFIG_FILE_EXT = @"appendExt";
|
|
18
19
|
NSString *const CONFIG_TRUSTY = @"trusty";
|
|
@@ -72,7 +72,8 @@
|
|
|
72
72
|
+ (NSDictionary *) stat:(NSString *) path error:(NSError **) error;
|
|
73
73
|
+ (void) exists:(NSString *) path callback:(RCTResponseSenderBlock)callback;
|
|
74
74
|
+ (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
|
|
75
|
-
+ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
|
|
75
|
+
+ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data transformFile:(BOOL)transformFile append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
|
|
76
|
+
+ (void) readFile:(NSString *)path encoding:(NSString *)encoding transformFile:(BOOL)transformFile onComplete:(void (^)(NSData * content, NSString* code, NSString * errMsg))onComplete;
|
|
76
77
|
+ (void) readFile:(NSString *)path encoding:(NSString *)encoding onComplete:(void (^)(NSData * content, NSString* code, NSString * errMsg))onComplete;
|
|
77
78
|
+ (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock;
|
|
78
79
|
+ (void) slice:(NSString *)path
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#import "ReactNativeBlobUtil.h"
|
|
11
11
|
#import "ReactNativeBlobUtilFS.h"
|
|
12
12
|
#import "ReactNativeBlobUtilConst.h"
|
|
13
|
+
#import "ReactNativeBlobUtilFileTransformer.h"
|
|
13
14
|
#import "IOS7Polyfill.h"
|
|
14
15
|
@import AssetsLibrary;
|
|
15
16
|
|
|
@@ -347,6 +348,7 @@ NSMutableDictionary *fileStreams = nil;
|
|
|
347
348
|
+ (void) writeFile:(NSString *)path
|
|
348
349
|
encoding:(NSString *)encoding
|
|
349
350
|
data:(NSString *)data
|
|
351
|
+
transformFile:(BOOL)transformFile
|
|
350
352
|
append:(BOOL)append
|
|
351
353
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
352
354
|
rejecter:(RCTPromiseRejectBlock)reject
|
|
@@ -394,6 +396,16 @@ NSMutableDictionary *fileStreams = nil;
|
|
|
394
396
|
else {
|
|
395
397
|
content = [data dataUsingEncoding:NSUTF8StringEncoding];
|
|
396
398
|
}
|
|
399
|
+
|
|
400
|
+
if (transformFile) {
|
|
401
|
+
NSObject<FileTransformer>* fileTransformer = [ReactNativeBlobUtilFileTransformer getFileTransformer];
|
|
402
|
+
if (fileTransformer) {
|
|
403
|
+
content = [fileTransformer onWriteFile:content];
|
|
404
|
+
} else {
|
|
405
|
+
return reject(@"EUNSPECIFIED",@"Transform specified but transformer not set", nil);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
397
409
|
if(append == YES) {
|
|
398
410
|
[fileHandle seekToEndOfFile];
|
|
399
411
|
[fileHandle writeData:content];
|
|
@@ -488,6 +500,7 @@ NSMutableDictionary *fileStreams = nil;
|
|
|
488
500
|
|
|
489
501
|
+ (void) readFile:(NSString *)path
|
|
490
502
|
encoding:(NSString *)encoding
|
|
503
|
+
transformFile:(BOOL) transformFile
|
|
491
504
|
onComplete:(void (^)(NSData * content, NSString * codeStr, NSString * errMsg))onComplete
|
|
492
505
|
{
|
|
493
506
|
[[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
|
|
@@ -522,6 +535,22 @@ NSMutableDictionary *fileStreams = nil;
|
|
|
522
535
|
|
|
523
536
|
}
|
|
524
537
|
|
|
538
|
+
if (transformFile) {
|
|
539
|
+
NSObject<FileTransformer>* fileTransformer = [ReactNativeBlobUtilFileTransformer getFileTransformer];
|
|
540
|
+
if (fileTransformer) {
|
|
541
|
+
@try{
|
|
542
|
+
fileContent = [fileTransformer onReadFile:fileContent];
|
|
543
|
+
} @catch (NSException * ex)
|
|
544
|
+
{
|
|
545
|
+
onComplete(nil, @"EUNSPECIFIED", [NSString stringWithFormat:@"Exception on File Transformer: '%@' ", [ex description]]);
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
} else {
|
|
549
|
+
onComplete(nil, @"EUNSPECIFIED", @"Transform specified but transformer not set");
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
525
554
|
if(encoding != nil)
|
|
526
555
|
{
|
|
527
556
|
if([[encoding lowercaseString] isEqualToString:@"utf8"])
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ReactNativeBlobUtilFileTransformer.h
|
|
2
|
+
// ReactNativeBlobUtil
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#ifndef ReactNativeBlobUtilDataConverter_h
|
|
6
|
+
#define ReactNativeBlobUtilDataConverter_h
|
|
7
|
+
|
|
8
|
+
#import <UIKit/UIKit.h>
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@protocol FileTransformer <NSObject>
|
|
12
|
+
- (NSData*) onWriteFile:(NSData*)data;
|
|
13
|
+
- (NSData*) onReadFile:(NSData*)data;
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
@interface ReactNativeBlobUtilFileTransformer : NSObject
|
|
17
|
+
|
|
18
|
+
+ (void) setFileTransformer:(NSObject<FileTransformer>*) fileTransformer;
|
|
19
|
+
+ (NSObject<FileTransformer>*) getFileTransformer;
|
|
20
|
+
|
|
21
|
+
@end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
#endif /* ReactNativeBlobUtilFileTransformer_h */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// ReactNativeBlobUtilFileTransformer.m
|
|
2
|
+
// ReactNativeBlobUtil
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
#import "ReactNativeBlobUtilFileTransformer.h"
|
|
6
|
+
|
|
7
|
+
static NSObject<FileTransformer> *sharedFileTransformer;
|
|
8
|
+
|
|
9
|
+
@implementation ReactNativeBlobUtilFileTransformer
|
|
10
|
+
|
|
11
|
+
+ (void) setFileTransformer:(NSObject<FileTransformer> *)fileTransformer {
|
|
12
|
+
sharedFileTransformer = fileTransformer;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
+ (NSObject<FileTransformer>*) getFileTransformer {
|
|
16
|
+
return sharedFileTransformer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@end
|
|
20
|
+
|
|
21
|
+
// PHOENIX:PATCH-PACKAGE END
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
if([orgPath hasPrefix:AL_PREFIX])
|
|
120
120
|
{
|
|
121
121
|
|
|
122
|
-
[ReactNativeBlobUtilFS readFile:orgPath encoding:nil onComplete:^(id content, NSString* code, NSString * err) {
|
|
122
|
+
[ReactNativeBlobUtilFS readFile:orgPath encoding:nil transformFile:false onComplete:^(id content, NSString* code, NSString * err) {
|
|
123
123
|
if(err != nil)
|
|
124
124
|
{
|
|
125
125
|
onComplete(nil, nil);
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
NSString * orgPath = [content substringFromIndex:[FILE_PREFIX length]];
|
|
224
224
|
orgPath = [ReactNativeBlobUtilFS getPathOfAsset:orgPath];
|
|
225
225
|
|
|
226
|
-
[ReactNativeBlobUtilFS readFile:orgPath encoding:nil onComplete:^(NSData *content, NSString* code, NSString * err) {
|
|
226
|
+
[ReactNativeBlobUtilFS readFile:orgPath encoding:nil transformFile:false onComplete:^(NSData *content, NSString* code, NSString * err) {
|
|
227
227
|
if(err != nil)
|
|
228
228
|
{
|
|
229
229
|
onComplete(formData, YES);
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
#import "ReactNativeBlobUtilFS.h"
|
|
12
12
|
#import "ReactNativeBlobUtilConst.h"
|
|
13
|
+
#import "ReactNativeBlobUtilFileTransformer.h"
|
|
13
14
|
#import "ReactNativeBlobUtilReqBuilder.h"
|
|
14
15
|
|
|
15
16
|
#import "IOS7Polyfill.h"
|
|
@@ -156,6 +157,12 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
|
|
|
156
157
|
} else {
|
|
157
158
|
destPath = [ReactNativeBlobUtilFS getTempPath:cacheKey withExtension:[self.options valueForKey:CONFIG_FILE_EXT]];
|
|
158
159
|
}
|
|
160
|
+
|
|
161
|
+
// We still need to initialize this as a placeholder in memory before we perform
|
|
162
|
+
// the conversion
|
|
163
|
+
if ([self ShouldTransformFile]) {
|
|
164
|
+
respData = [[NSMutableData alloc] init];
|
|
165
|
+
}
|
|
159
166
|
} else {
|
|
160
167
|
respData = [[NSMutableData alloc] init];
|
|
161
168
|
respFile = NO;
|
|
@@ -333,7 +340,9 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
|
|
|
333
340
|
chunkString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
334
341
|
}
|
|
335
342
|
|
|
336
|
-
|
|
343
|
+
// If we need to process the data, we defer writing into the file until the we have all the data, at which point
|
|
344
|
+
// we can perform the processing and then write into the file
|
|
345
|
+
if (respFile && ![self ShouldTransformFile]) {
|
|
337
346
|
[writeStream write:[data bytes] maxLength:[data length]];
|
|
338
347
|
} else {
|
|
339
348
|
[respData appendData:data];
|
|
@@ -390,6 +399,22 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
|
|
|
390
399
|
}
|
|
391
400
|
|
|
392
401
|
if (respFile) {
|
|
402
|
+
if ([self ShouldTransformFile]) {
|
|
403
|
+
// At this point, we have the data that we deferred to write into a file. We can now
|
|
404
|
+
// perform the conversion and write the converted data into the file.
|
|
405
|
+
NSObject<FileTransformer>* fileTransformer = [ReactNativeBlobUtilFileTransformer getFileTransformer];
|
|
406
|
+
if (!fileTransformer) {
|
|
407
|
+
errMsg = @"Transform file specified but file transfomer not set";
|
|
408
|
+
} else {
|
|
409
|
+
@try{
|
|
410
|
+
NSData* transformedData = [fileTransformer onWriteFile:respData];
|
|
411
|
+
[writeStream write:[transformedData bytes] maxLength:[transformedData length]];
|
|
412
|
+
} @catch(NSException * ex)
|
|
413
|
+
{
|
|
414
|
+
errMsg = [NSString stringWithFormat:@"Exception on File Transformer: '%@' ", [ex description]];
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
393
418
|
[writeStream close];
|
|
394
419
|
rnfbRespType = RESP_TYPE_PATH;
|
|
395
420
|
respStr = destPath;
|
|
@@ -430,6 +455,10 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
|
|
|
430
455
|
|
|
431
456
|
}
|
|
432
457
|
|
|
458
|
+
- (BOOL) ShouldTransformFile{
|
|
459
|
+
return [[options valueForKey:CONFIG_TRANSFORM_FILE] boolValue];
|
|
460
|
+
}
|
|
461
|
+
|
|
433
462
|
// upload progress handler
|
|
434
463
|
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesWritten totalBytesExpectedToSend:(int64_t)totalBytesExpectedToWrite
|
|
435
464
|
{
|
package/mediacollection.js
CHANGED
|
@@ -9,7 +9,11 @@ function createMediafile(fd: filedescriptor, mediatype: string): Promise {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
function writeToMediafile(uri: string, path: string) {
|
|
12
|
-
return ReactNativeBlobUtil.writeToMediaFile(uri, path);
|
|
12
|
+
return ReactNativeBlobUtil.writeToMediaFile(uri, path, false);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function writeToMediafileWithTransform(uri: string, path: string) {
|
|
16
|
+
return ReactNativeBlobUtil.writeToMediaFile(uri, path, true);
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
function copyToInternal(contenturi: string, destpath: string) {
|
|
@@ -27,6 +31,7 @@ function copyToMediaStore(fd: filedescriptor, mediatype: string, path: string) {
|
|
|
27
31
|
export default {
|
|
28
32
|
createMediafile,
|
|
29
33
|
writeToMediafile,
|
|
34
|
+
writeToMediafileWithTransform,
|
|
30
35
|
copyToInternal,
|
|
31
36
|
getBlob,
|
|
32
37
|
copyToMediaStore
|
package/package.json
CHANGED
package/polyfill/Fetch.js
CHANGED
|
@@ -59,10 +59,12 @@ class ReactNativeBlobUtilFetchPolyfill {
|
|
|
59
59
|
// task.then is not, so we have to extend task.then with progress and
|
|
60
60
|
// cancel function
|
|
61
61
|
let progressHandler, uploadHandler, cancelHandler;
|
|
62
|
+
let scopedTask = null;
|
|
62
63
|
let statefulPromise = promise
|
|
63
64
|
.then((body) => {
|
|
64
65
|
let task = RNconfig(config)
|
|
65
66
|
.fetch(options.method, url, options.headers, body);
|
|
67
|
+
scopedTask = task;
|
|
66
68
|
if (progressHandler)
|
|
67
69
|
task.progress(progressHandler);
|
|
68
70
|
if (uploadHandler)
|
|
@@ -87,8 +89,8 @@ class ReactNativeBlobUtilFetchPolyfill {
|
|
|
87
89
|
};
|
|
88
90
|
statefulPromise.cancel = () => {
|
|
89
91
|
cancelHandler = true;
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
+
if (scopedTask && scopedTask.cancel)
|
|
93
|
+
scopedTask.cancel();
|
|
92
94
|
};
|
|
93
95
|
|
|
94
96
|
return statefulPromise;
|