react-native-blob-util 0.17.2 → 0.18.1

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 (27) hide show
  1. package/README.md +12 -5
  2. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConst.java +1 -0
  3. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFS.java +2 -3
  4. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +29 -12
  5. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilStream.java +8 -3
  6. package/android/src/newarch/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java +11 -0
  7. package/android/src/oldarch/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java +11 -0
  8. package/class/ReactNativeBlobUtilReadStream.js +66 -62
  9. package/class/ReactNativeBlobUtilSession.js +6 -11
  10. package/class/ReactNativeBlobUtilWriteStream.js +4 -9
  11. package/codegenSpecs/NativeBlobUtils.js +6 -9
  12. package/fetch.js +30 -23
  13. package/index.d.ts +4 -0
  14. package/index.js +2 -14
  15. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.h +5 -4
  16. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.mm +44 -26
  17. package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +117 -36
  18. package/ios/ReactNativeBlobUtilConst.h +1 -0
  19. package/ios/ReactNativeBlobUtilConst.mm +1 -0
  20. package/ios/ReactNativeBlobUtilFS.h +1 -4
  21. package/ios/ReactNativeBlobUtilFS.mm +24 -30
  22. package/ios/ReactNativeBlobUtilNetwork.h +1 -2
  23. package/ios/ReactNativeBlobUtilNetwork.mm +2 -24
  24. package/ios/ReactNativeBlobUtilRequest.h +3 -4
  25. package/ios/ReactNativeBlobUtilRequest.mm +8 -17
  26. package/package.json +4 -4
  27. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj +2 -1
package/README.md CHANGED
@@ -27,7 +27,7 @@ react-native-blob-util version **0.10.16** and up is only compatible with react
27
27
  - JSON stream supported base on [Oboe.js](https://github.com/jimhigson/oboe.js/) @jimhigson
28
28
 
29
29
  ## React Native New Architecture
30
- With Reacht Native 0.68.0 the switch to enable the new aritechture was introduced.
30
+ With React Native 0.68.0 the switch to enable the new aritechture was introduced.
31
31
  Starting with version 0.17.0 this library introduces support for the new architecture as well. Of course the old architecture will still be supproted.
32
32
  Further information about it and how to use it you can find here: https://reactnative.dev/docs/next/the-new-architecture/landing-page
33
33
 
@@ -92,14 +92,21 @@ After `0.10.3` you can install this package directly from Github
92
92
  npm install --save github:RonRadtke/react-native-blob-util#<branch_name>
93
93
  ```
94
94
 
95
+ **iOS**
96
+
97
+ When using the package from npm, run `pod install` from the `ios` directory:
98
+
99
+ ```sh
100
+ cd ios; pod install; cd ..
101
+ ```
102
+
95
103
  **Okhttp**
96
104
 
97
105
  For using the library okhttp3 is required. It's in general included in react-native. The library uses the okhttp version shipped with react-native or used by your app. For very old devices android devices okhttp 3.12 can be used.
98
106
 
99
107
  **Manually Link Native Modules**
100
108
 
101
- If you're using RN 0.60 or higher, manuall linking should not be required anymore.
102
-
109
+ If you're using RN 0.60 or higher, manual linking should not be required anymore.
103
110
 
104
111
  If automatically linking doesn't work for you, see instructions on [manually linking](https://github.com/RonRadtke/react-native-blob-util/wiki/Manually-Link-Package#index).
105
112
 
@@ -658,14 +665,14 @@ Android 10 introduced scoped storage and thus new APIs to store files to Documen
658
665
 
659
666
  #### CopyToMediaStore
660
667
 
661
- Copies an existing file from the internal Storage to the Media Store. <br> An exmaple for downloading a file and storing it to the `downloads` collection
668
+ Copies an existing file from the internal Storage to the Media Store. <br> An example for downloading a file and storing it to the `downloads` collection
662
669
 
663
670
  ```js
664
671
  ReactNativeBlobUtil
665
672
  .config({
666
673
  fileCache: true
667
674
  })
668
- .fetch('GET', 'https://example.de/image.png', {'Accept': 'application/octet-stream'}, JSON.stringify(dat))
675
+ .fetch('GET', 'https://example.de/image.png')
669
676
  .then(async (res) => {
670
677
  let result = await ReactNativeBlobUtil.MediaCollection.copyToMediaStore({
671
678
  name: filename, // name of the file
@@ -6,6 +6,7 @@ public class ReactNativeBlobUtilConst {
6
6
  public static final String EVENT_PROGRESS = "ReactNativeBlobUtilProgress";
7
7
  public static final String EVENT_HTTP_STATE = "ReactNativeBlobUtilState";
8
8
  public static final String EVENT_MESSAGE = "ReactNativeBlobUtilMessage";
9
+ public static final String EVENT_FILESYSTEM = "ReactNativeBlobUtilFilesystem";
9
10
  public static final String FILE_PREFIX = "ReactNativeBlobUtil-file://";
10
11
  public static final String CONTENT_PREFIX = "ReactNativeBlobUtil-content://";
11
12
  public static final String FILE_PREFIX_BUNDLE_ASSET = "bundle-assets://";
@@ -19,6 +19,8 @@ import com.facebook.react.bridge.ReadableArray;
19
19
  import com.facebook.react.bridge.WritableArray;
20
20
  import com.facebook.react.bridge.WritableMap;
21
21
  import com.facebook.react.modules.core.DeviceEventManagerModule;
22
+ import com.facebook.react.uimanager.UIManagerHelper;
23
+ import com.facebook.react.uimanager.events.EventDispatcher;
22
24
 
23
25
  import java.io.File;
24
26
  import java.io.FileInputStream;
@@ -37,9 +39,6 @@ class ReactNativeBlobUtilFS {
37
39
 
38
40
  private ReactApplicationContext mCtx;
39
41
  private DeviceEventManagerModule.RCTDeviceEventEmitter emitter;
40
- private String encoding = "base64";
41
- private OutputStream writeStreamInstance = null;
42
- private static HashMap<String, ReactNativeBlobUtilFS> fileStreams = new HashMap<>();
43
42
 
44
43
  ReactNativeBlobUtilFS(ReactApplicationContext ctx) {
45
44
  this.mCtx = ctx;
@@ -13,6 +13,7 @@ import android.net.NetworkInfo;
13
13
  import android.net.Uri;
14
14
  import android.os.Build;
15
15
  import android.os.Bundle;
16
+ import android.os.Environment;
16
17
  import android.os.Handler;
17
18
  import android.os.Message;
18
19
  import android.util.Base64;
@@ -49,6 +50,8 @@ import java.nio.charset.CharsetDecoder;
49
50
  import java.util.ArrayList;
50
51
  import java.util.HashMap;
51
52
 
53
+ import java.util.UUID;
54
+
52
55
  import java.util.List;
53
56
  import java.util.Locale;
54
57
  import java.util.concurrent.Executors;
@@ -252,19 +255,29 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
252
255
  if (options.addAndroidDownloads.hasKey("path")) {
253
256
  req.setDestinationUri(Uri.parse("file://" + options.addAndroidDownloads.getString("path")));
254
257
  }
255
- // #391 Add MIME type to the request
256
258
  if (options.addAndroidDownloads.hasKey("mime")) {
257
259
  req.setMimeType(options.addAndroidDownloads.getString("mime"));
258
260
  }
259
261
  if (options.addAndroidDownloads.hasKey("mediaScannable") && options.addAndroidDownloads.getBoolean("mediaScannable")) {
260
262
  req.allowScanningByMediaScanner();
261
263
  }
264
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.addAndroidDownloads.hasKey("storeInDownloads") && options.addAndroidDownloads.getBoolean("storeInDownloads")) {
265
+ String t = options.addAndroidDownloads.getString("title");
266
+ if(t == null || t.isEmpty())
267
+ t = UUID.randomUUID().toString();
268
+ if(this.options.appendExt != null && !this.options.appendExt.isEmpty())
269
+ t += "." + this.options.appendExt;
270
+
271
+ req.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, t);
272
+ }
273
+
262
274
  // set headers
263
275
  ReadableMapKeySetIterator it = headers.keySetIterator();
264
276
  while (it.hasNextKey()) {
265
277
  String key = it.nextKey();
266
278
  req.addRequestHeader(key, headers.getString(key));
267
279
  }
280
+
268
281
  // Attempt to add cookie, if it exists
269
282
  URL urlObj;
270
283
  try {
@@ -862,9 +875,8 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
862
875
  DownloadManager dm = (DownloadManager) appCtx.getSystemService(Context.DOWNLOAD_SERVICE);
863
876
  dm.query(query);
864
877
  Cursor c = dm.query(query);
865
- // #236 unhandled null check for DownloadManager.query() return value
866
878
  if (c == null) {
867
- this.callback.invoke("Download manager failed to download from " + this.url + ". Query was unsuccessful ", null, null);
879
+ this.invoke_callback("Download manager failed to download from " + this.url + ". Query was unsuccessful ", null, null);
868
880
  return;
869
881
  }
870
882
 
@@ -872,10 +884,9 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
872
884
  try {
873
885
  // the file exists in media content database
874
886
  if (c.moveToFirst()) {
875
- // #297 handle failed request
876
887
  int statusCode = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
877
888
  if (statusCode == DownloadManager.STATUS_FAILED) {
878
- this.callback.invoke("Download manager failed to download from " + this.url + ". Status Code = " + statusCode, null, null);
889
+ this.invoke_callback("Download manager failed to download from " + this.url + ". Status Code = " + statusCode, null, null);
879
890
  return;
880
891
  }
881
892
  String contentUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
@@ -904,17 +915,25 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
904
915
  if (!exists)
905
916
  throw new Exception("Download manager download failed, the file does not downloaded to destination.");
906
917
  else
907
- this.callback.invoke(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, customDest);
918
+ this.invoke_callback(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, customDest);
908
919
 
909
920
  } catch (Exception ex) {
910
921
  ex.printStackTrace();
911
- this.callback.invoke(ex.getLocalizedMessage(), null);
922
+ this.invoke_callback(ex.getLocalizedMessage(), null);
912
923
  }
913
- } else {
924
+ }
925
+ else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.addAndroidDownloads.hasKey("storeInDownloads") && options.addAndroidDownloads.getBoolean("storeInDownloads")){
926
+ Uri downloadeduri = dm.getUriForDownloadedFile(downloadManagerId);
927
+ if(downloadeduri == null)
928
+ this.callback.invoke("Download manager could not resolve downloaded file uri.", ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, null);
929
+ else
930
+ this.callback.invoke(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, downloadeduri.toString());
931
+ }
932
+ else {
914
933
  if (filePath == null)
915
- this.callback.invoke("Download manager could not resolve downloaded file path.", ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, null);
934
+ this.invoke_callback("Download manager could not resolve downloaded file path.", ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, null);
916
935
  else
917
- this.callback.invoke(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, filePath);
936
+ this.invoke_callback(null, ReactNativeBlobUtilConst.RNFB_RESPONSE_PATH, filePath);
918
937
  }
919
938
 
920
939
  }
@@ -946,6 +965,4 @@ public class ReactNativeBlobUtilReq extends BroadcastReceiver implements Runnabl
946
965
 
947
966
  return client;
948
967
  }
949
-
950
-
951
968
  }
@@ -1,5 +1,7 @@
1
1
  package com.ReactNativeBlobUtil;
2
2
 
3
+ import static com.ReactNativeBlobUtil.ReactNativeBlobUtilConst.EVENT_FILESYSTEM;
4
+
3
5
  import android.net.Uri;
4
6
  import android.os.SystemClock;
5
7
  import android.util.Base64;
@@ -249,7 +251,8 @@ public class ReactNativeBlobUtilStream {
249
251
  WritableMap eventData = Arguments.createMap();
250
252
  eventData.putString("event", event);
251
253
  eventData.putString("detail", data);
252
- this.emitter.emit(streamName, eventData);
254
+ eventData.putString("streamId", streamName);
255
+ this.emitter.emit(EVENT_FILESYSTEM, eventData);
253
256
  }
254
257
 
255
258
  // "event" always is "data"...
@@ -257,7 +260,8 @@ public class ReactNativeBlobUtilStream {
257
260
  WritableMap eventData = Arguments.createMap();
258
261
  eventData.putString("event", event);
259
262
  eventData.putArray("detail", data);
260
- this.emitter.emit(streamName, eventData);
263
+ eventData.putString("streamId", streamName);
264
+ this.emitter.emit(EVENT_FILESYSTEM, eventData);
261
265
  }
262
266
 
263
267
  // "event" always is "error"...
@@ -266,7 +270,8 @@ public class ReactNativeBlobUtilStream {
266
270
  eventData.putString("event", event);
267
271
  eventData.putString("code", code);
268
272
  eventData.putString("detail", message);
269
- this.emitter.emit(streamName, eventData);
273
+ eventData.putString("streamId", streamName);
274
+ this.emitter.emit(EVENT_FILESYSTEM, eventData);
270
275
  }
271
276
 
272
277
  /**
@@ -26,6 +26,17 @@ public class ReactNativeBlobUtil extends NativeBlobUtilsSpec {
26
26
  delegate = new ReactNativeBlobUtilImpl(reactContext);
27
27
  }
28
28
 
29
+ // Required for rn built in EventEmitter Calls.
30
+ @ReactMethod
31
+ public void addListener(String eventName) {
32
+
33
+ }
34
+
35
+ @ReactMethod
36
+ public void removeListeners(Integer count) {
37
+
38
+ }
39
+
29
40
  @Override
30
41
  protected Map<String, Object> getTypedExportedConstants() {
31
42
  Map<String, Object> res = new HashMap<>();
@@ -27,6 +27,17 @@ public class ReactNativeBlobUtil extends ReactContextBaseJavaModule {
27
27
  delegate = new ReactNativeBlobUtilImpl(reactContext);
28
28
  }
29
29
 
30
+ // Required for rn built in EventEmitter Calls.
31
+ @ReactMethod
32
+ public void addListener(String eventName) {
33
+
34
+ }
35
+
36
+ @ReactMethod
37
+ public void removeListeners(Integer count) {
38
+
39
+ }
40
+
30
41
  @NonNull
31
42
  @Override
32
43
  public String getName() {
@@ -2,80 +2,84 @@
2
2
  // Use of this source code is governed by a MIT-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import {
6
- DeviceEventEmitter,
7
- NativeAppEventEmitter,
8
- } from 'react-native';
5
+ import {NativeEventEmitter} from 'react-native';
9
6
  import UUID from '../utils/uuid';
10
7
 
11
8
  import ReactNativeBlobUtil from "../codegenSpecs/NativeBlobUtils";
12
- const emitter = DeviceEventEmitter;
9
+
10
+ const emitter = new NativeEventEmitter(ReactNativeBlobUtil);
13
11
 
14
12
  export default class ReactNativeBlobUtilReadStream {
15
13
 
16
- path : string;
17
- encoding : 'utf8' | 'ascii' | 'base64';
18
- bufferSize : ?number;
19
- closed : boolean;
20
- tick : number = 10;
14
+ path: string;
15
+ encoding: 'utf8' | 'ascii' | 'base64';
16
+ bufferSize: ?number;
17
+ closed: boolean;
18
+ tick: number = 10;
21
19
 
22
- constructor(path:string, encoding:string, bufferSize?:?number, tick:number) {
23
- if(!path)
24
- throw Error('ReactNativeBlobUtil could not open file stream with empty `path`');
25
- this.encoding = encoding || 'utf8';
26
- this.bufferSize = bufferSize;
27
- this.path = path;
28
- this.closed = false;
29
- this.tick = tick;
30
- this._onData = () => {};
31
- this._onEnd = () => {};
32
- this._onError = () => {};
33
- this.streamId = 'RNFBRS'+ UUID();
20
+ constructor(path: string, encoding: string, bufferSize?: ?number, tick: number) {
21
+ if (!path)
22
+ throw Error('ReactNativeBlobUtil could not open file stream with empty `path`');
23
+ this.encoding = encoding || 'utf8';
24
+ this.bufferSize = bufferSize;
25
+ this.path = path;
26
+ this.closed = false;
27
+ this.tick = tick;
28
+ this._onData = () => {
29
+ };
30
+ this._onEnd = () => {
31
+ };
32
+ this._onError = () => {
33
+ };
34
+ this.streamId = 'RNFBRS' + UUID();
34
35
 
35
- // register for file stream event
36
- let subscription = emitter.addListener(this.streamId, (e) => {
37
- let {event, code, detail} = e;
38
- if(this._onData && event === 'data') {
39
- this._onData(detail);
40
- return;
41
- }
42
- else if (this._onEnd && event === 'end') {
43
- this._onEnd(detail);
44
- }
45
- else {
46
- const err = new Error(detail);
47
- err.code = code || 'EUNSPECIFIED';
48
- if(this._onError)
49
- this._onError(err);
50
- else
51
- throw err;
52
- }
53
- // when stream closed or error, remove event handler
54
- if (event === 'error' || event === 'end') {
55
- subscription.remove();
56
- this.closed = true;
57
- }
58
- });
36
+ // register for file stream event
37
+ let subscription = emitter.addListener('ReactNativeBlobUtilFilesystem', (e) => {
38
+ if (typeof e === 'string') e = JSON.parse(e);
39
+ console.log(e, this.streamId, e.streamId, e.streamId === this.streamId)
40
+ if (e.streamId !== this.streamId) return; // wrong stream
41
+ let {event, code, detail} = e;
42
+ if (this._onData && event === 'data') {
43
+ this._onData(detail);
44
+ return;
45
+ }
46
+ else if (this._onEnd && event === 'end') {
47
+ this._onEnd(detail);
48
+ }
49
+ else {
50
+ const err = new Error(detail);
51
+ err.code = code || 'EUNSPECIFIED';
52
+ if (this._onError)
53
+ this._onError(err);
54
+ else
55
+ throw err;
56
+ }
57
+ // when stream closed or error, remove event handler
58
+ if (event === 'error' || event === 'end') {
59
+ subscription.remove();
60
+ this.closed = true;
61
+ }
62
+ });
59
63
 
60
- }
64
+ }
61
65
 
62
- open() {
63
- if(!this.closed)
64
- ReactNativeBlobUtil.readStream(this.path, this.encoding, this.bufferSize || 10240 , this.tick || -1, this.streamId);
65
- else
66
- throw new Error('Stream closed');
67
- }
66
+ open() {
67
+ if (!this.closed)
68
+ ReactNativeBlobUtil.readStream(this.path, this.encoding, this.bufferSize || 10240, this.tick || -1, this.streamId);
69
+ else
70
+ throw new Error('Stream closed');
71
+ }
68
72
 
69
- onData(fn:() => void) {
70
- this._onData = fn;
71
- }
73
+ onData(fn: () => void) {
74
+ this._onData = fn;
75
+ }
72
76
 
73
- onError(fn) {
74
- this._onError = fn;
75
- }
77
+ onError(fn) {
78
+ this._onError = fn;
79
+ }
76
80
 
77
- onEnd (fn) {
78
- this._onEnd = fn;
79
- }
81
+ onEnd(fn) {
82
+ this._onEnd = fn;
83
+ }
80
84
 
81
85
  }
@@ -2,12 +2,7 @@
2
2
  // Use of this source code is governed by a MIT-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import {
6
- DeviceEventEmitter,
7
- NativeAppEventEmitter,
8
- } from 'react-native';
9
-
10
- import ReactNativeBlobUtil from "../codegenSpecs/NativeBlobUtils";
5
+ import ReactNativeBlobUtil from '../codegenSpecs/NativeBlobUtils';
11
6
 
12
7
  let sessions = {};
13
8
 
@@ -29,8 +24,8 @@ export default class ReactNativeBlobUtilSession {
29
24
 
30
25
  constructor(name:string, list:Array<string>) {
31
26
  this.name = name;
32
- if(!sessions[name]) {
33
- if(Array.isArray(list))
27
+ if (!sessions[name]) {
28
+ if (Array.isArray(list))
34
29
  sessions[name] = list;
35
30
  else
36
31
  sessions[name] = [];
@@ -44,8 +39,8 @@ export default class ReactNativeBlobUtilSession {
44
39
 
45
40
  remove(path:string):ReactNativeBlobUtilSession {
46
41
  let list = sessions[this.name];
47
- for(let i of list) {
48
- if(list[i] === path) {
42
+ for (let i of list) {
43
+ if (list[i] === path) {
49
44
  sessions[this.name].splice(i, 1);
50
45
  break;
51
46
  }
@@ -60,7 +55,7 @@ export default class ReactNativeBlobUtilSession {
60
55
  dispose():Promise {
61
56
  return new Promise((resolve, reject) => {
62
57
  ReactNativeBlobUtil.removeSession(sessions[this.name], (err) => {
63
- if(err)
58
+ if (err)
64
59
  reject(new Error(err));
65
60
  else {
66
61
  delete sessions[this.name];
@@ -2,12 +2,7 @@
2
2
  // Use of this source code is governed by a MIT-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import {
6
- DeviceEventEmitter,
7
- NativeAppEventEmitter,
8
- } from 'react-native';
9
-
10
- import ReactNativeBlobUtil from "../codegenSpecs/NativeBlobUtils";
5
+ import ReactNativeBlobUtil from '../codegenSpecs/NativeBlobUtils';
11
6
  export default class ReactNativeBlobUtilWriteStream {
12
7
 
13
8
  id : string;
@@ -24,17 +19,17 @@ export default class ReactNativeBlobUtilWriteStream {
24
19
  return new Promise((resolve, reject) => {
25
20
  try {
26
21
  let method = this.encoding === 'ascii' ? 'writeArrayChunk' : 'writeChunk';
27
- if(this.encoding.toLocaleLowerCase() === 'ascii' && !Array.isArray(data)) {
22
+ if (this.encoding.toLocaleLowerCase() === 'ascii' && !Array.isArray(data)) {
28
23
  reject(new Error('ascii input data must be an Array'));
29
24
  return;
30
25
  }
31
26
  ReactNativeBlobUtil[method](this.id, data, (error) => {
32
- if(error)
27
+ if (error)
33
28
  reject(new Error(error));
34
29
  else
35
30
  resolve(this);
36
31
  });
37
- } catch(err) {
32
+ } catch (err) {
38
33
  reject(new Error(err));
39
34
  }
40
35
  });
@@ -66,9 +66,9 @@ export interface Spec extends TurboModule {
66
66
  // Android Only APIs
67
67
  +actionViewIntent: (path: string, mime: string, chooserTitle: string) => Promise<void>;
68
68
  +addCompleteDownload: (config: Object) => Promise<void>;
69
- +copyToInternal: (contentUri: string, destpath: string) => Promise<string>;
69
+ +copyToInternal: (contentUri: string, destpath: string) => Promise<string>;
70
70
  +copyToMediaStore: (filedata: Object, mt: string, path: string) => Promise<string>;
71
- +createMediaFile: (filedata: Object, mt: string) => Promise<string>;
71
+ +createMediaFile: (filedata: Object, mt: string) => Promise<string>;
72
72
  +getBlob: (contentUri: string, encoding: string) => Promise<Array<any>>;
73
73
  +getContentIntent: (mime: string) => Promise<string>;
74
74
  +getSDCardDir: () => Promise<string>;
@@ -76,10 +76,7 @@ export interface Spec extends TurboModule {
76
76
  +scanFile: (pairs: Array<any>, callback: (value: Array<any>) => void) => void;
77
77
  +writeToMediaFile: (fileUri: string, path: string, transformFile: boolean) => Promise<string>;
78
78
  }
79
-
80
- export default (TurboModuleRegistry.get<Spec>(
81
- 'ReactNativeBlobUtil'
82
- ): ?Spec);
83
-
84
-
85
-
79
+
80
+ export default (TurboModuleRegistry.get<Spec>('ReactNativeBlobUtil'): ?Spec);
81
+
82
+
package/fetch.js CHANGED
@@ -1,17 +1,19 @@
1
- import {ReactNativeBlobUtilConfig} from "./types";
2
- import URIUtil from "./utils/uri";
3
- import fs from "./fs";
4
- import getUUID from "./utils/uuid";
5
- import {DeviceEventEmitter} from "react-native";
6
- import {FetchBlobResponse} from "./class/ReactNativeBlobUtilBlobResponse";
7
- import CanceledFetchError from "./class/ReactNativeBlobUtilCanceledFetchError";
8
- import ReactNativeBlobUtil from "./codegenSpecs/NativeBlobUtils";
1
+ import {ReactNativeBlobUtilConfig} from 'types';
2
+ import URIUtil from './utils/uri';
3
+ import fs from './fs';
4
+ import getUUID from './utils/uuid';
5
+ import {NativeEventEmitter} from 'react-native';
6
+ import {FetchBlobResponse} from './class/ReactNativeBlobUtilBlobResponse';
7
+ import CanceledFetchError from './class/ReactNativeBlobUtilCanceledFetchError';
8
+ import ReactNativeBlobUtil from './codegenSpecs/NativeBlobUtils';
9
9
 
10
- const emitter = DeviceEventEmitter;
10
+ const eventEmitter = new NativeEventEmitter(ReactNativeBlobUtil);
11
11
 
12
12
  // register message channel event handler.
13
- emitter.addListener("ReactNativeBlobUtilMessage", (e) => {
13
+ eventEmitter.addListener('ReactNativeBlobUtilMessage', (e) => {
14
+ if (typeof e === 'string') e = JSON.parse(e);
14
15
 
16
+ console.log('add listener')
15
17
  if (e.event === 'warn') {
16
18
  console.warn(e.detail);
17
19
  }
@@ -19,7 +21,7 @@ emitter.addListener("ReactNativeBlobUtilMessage", (e) => {
19
21
  throw e.detail;
20
22
  }
21
23
  else {
22
- console.log("ReactNativeBlobUtil native message", e.detail);
24
+ console.log('ReactNativeBlobUtil native message', e.detail);
23
25
  }
24
26
  });
25
27
 
@@ -105,7 +107,7 @@ function fetchFile(options = {}, method, url, headers = {}, body): Promise {
105
107
  .then((stream) => new Promise((resolve, reject) => {
106
108
  stream.open();
107
109
  info = {
108
- state: "2",
110
+ state: '2',
109
111
  headers: {'source': 'system-fs'},
110
112
  status: 200,
111
113
  respType: 'text',
@@ -188,31 +190,36 @@ export function fetch(...args: any): Promise {
188
190
  let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob';
189
191
 
190
192
  // on progress event listener
191
- subscription = emitter.addListener('ReactNativeBlobUtilProgress', (e) => {
193
+ subscription = eventEmitter.addListener('ReactNativeBlobUtilProgress', (e) => {
194
+ if (typeof e === 'string') e = JSON.parse(e);
192
195
  if (e.taskId === taskId && promise.onProgress) {
193
196
  promise.onProgress(e.written, e.total, e.chunk);
194
197
  }
195
198
  });
196
199
 
197
- subscriptionUpload = emitter.addListener('ReactNativeBlobUtilProgress-upload', (e) => {
200
+ subscriptionUpload = eventEmitter.addListener('ReactNativeBlobUtilProgress-upload', (e) => {
201
+ if (typeof e === 'string') e = JSON.parse(e);
198
202
  if (e.taskId === taskId && promise.onUploadProgress) {
199
203
  promise.onUploadProgress(e.written, e.total);
200
204
  }
201
205
  });
202
206
 
203
- stateEvent = emitter.addListener('ReactNativeBlobUtilState', (e) => {
207
+ stateEvent = eventEmitter.addListener('ReactNativeBlobUtilState', (e) => {
208
+ if (typeof e === 'string') e = JSON.parse(e);
204
209
  if (e.taskId === taskId)
205
210
  respInfo = e;
206
211
  promise.onStateChange && promise.onStateChange(e);
207
212
  });
208
213
 
209
- subscription = emitter.addListener('ReactNativeBlobUtilExpire', (e) => {
214
+ subscription = eventEmitter.addListener('ReactNativeBlobUtilExpire', (e) => {
215
+ if (typeof e === 'string') e = JSON.parse(e);
210
216
  if (e.taskId === taskId && promise.onExpire) {
211
217
  promise.onExpire(e);
212
218
  }
213
219
  });
214
220
 
215
- partEvent = emitter.addListener('ReactNativeBlobUtilServerPush', (e) => {
221
+ partEvent = eventEmitter.addListener('ReactNativeBlobUtilServerPush', (e) => {
222
+ if (typeof e === 'string') e = JSON.parse(e);
216
223
  if (e.taskId === taskId && promise.onPartData) {
217
224
  promise.onPartData(e.chunk);
218
225
  }
@@ -244,11 +251,11 @@ export function fetch(...args: any): Promise {
244
251
  subscriptionUpload.remove();
245
252
  stateEvent.remove();
246
253
  partEvent.remove();
247
- delete promise['progress'];
248
- delete promise['uploadProgress'];
249
- delete promise['stateChange'];
250
- delete promise['part'];
251
- delete promise['cancel'];
254
+ delete promise.progress;
255
+ delete promise.uploadProgress;
256
+ delete promise.stateChange;
257
+ delete promise.part;
258
+ delete promise.cancel;
252
259
  // delete promise['expire']
253
260
  promise.cancel = () => {
254
261
  };
@@ -329,7 +336,7 @@ export function fetch(...args: any): Promise {
329
336
  subscriptionUpload.remove();
330
337
  stateEvent.remove();
331
338
  ReactNativeBlobUtil.cancelRequest(taskId, fn);
332
- promiseReject(new CanceledFetchError("canceled"));
339
+ promiseReject(new CanceledFetchError('canceled'));
333
340
  };
334
341
  promise.taskId = taskId;
335
342
 
package/index.d.ts CHANGED
@@ -782,6 +782,10 @@ export interface AddAndroidDownloads {
782
782
  * (https://developer.android.com/reference/android/app/DownloadManager.html#addCompletedDownload(java.lang.String, java.lang.String, boolean, java.lang.String, java.lang.String, long, boolean))
783
783
  */
784
784
  mediaScannable?: boolean;
785
+ /**
786
+ * Only for Android >= Q; Enforces the file being stored to the MediaCollection Downloads. This might overwrite any value given in "path"
787
+ */
788
+ storeInDownloads?: boolean;
785
789
  /**
786
790
  * A boolean value decide whether show a notification when download complete.
787
791
  */