Browse Source

wifi only option, and missing typings.

Cristiano Coelho 4 years ago
parent
commit
3bbe72daac

+ 35
- 11
README.md View File

41
 
41
 
42
 ## About
42
 ## About
43
 
43
 
44
-This project was started in the cause of solving issue [facebook/react-native#854](https://github.com/facebook/react-native/issues/854), React Native's lacks of `Blob` implementation which results into problems when transferring binary data. 
44
+This project was started in the cause of solving issue [facebook/react-native#854](https://github.com/facebook/react-native/issues/854), React Native's lacks of `Blob` implementation which results into problems when transferring binary data.
45
 
45
 
46
 It is committed to making file access and transfer easier and more efficient for React Native developers. We've implemented highly customizable filesystem and network module which plays well together. For example, developers can upload and download data directly from/to storage, which is more efficient, especially for large files. The file system supports file stream, so you don't have to worry about OOM problem when accessing large files.
46
 It is committed to making file access and transfer easier and more efficient for React Native developers. We've implemented highly customizable filesystem and network module which plays well together. For example, developers can upload and download data directly from/to storage, which is more efficient, especially for large files. The file system supports file stream, so you don't have to worry about OOM problem when accessing large files.
47
 
47
 
116
 
116
 
117
     <uses-permission android:name="android.permission.INTERNET" />
117
     <uses-permission android:name="android.permission.INTERNET" />
118
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
118
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
119
-+   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />                                               
120
-+   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />                                              
119
++   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
120
++   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
121
 +   <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
121
 +   <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
122
     ...
122
     ...
123
 
123
 
129
     <intent-filter>
129
     <intent-filter>
130
             <action android:name="android.intent.action.MAIN" />
130
             <action android:name="android.intent.action.MAIN" />
131
             <category android:name="android.intent.category.LAUNCHER" />
131
             <category android:name="android.intent.category.LAUNCHER" />
132
-+           <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>                          
132
++           <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
133
     </intent-filter>
133
     </intent-filter>
134
 ```
134
 ```
135
 
135
 
136
+If you are going to use the `wifiOnly` flag, you need to add this to `AndroidManifest.xml`
137
+
138
+```diff
139
++   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
140
+    ...
141
+
142
+```
143
+
136
 **Grant Access Permission for Android 6.0**
144
 **Grant Access Permission for Android 6.0**
137
 
145
 
138
 Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. So adding permissions in `AndroidManifest.xml` won't work for Android 6.0+ devices. To grant permissions in runtime, you might use [PermissionAndroid API](https://facebook.github.io/react-native/docs/permissionsandroid.html).
146
 Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. So adding permissions in `AndroidManifest.xml` won't work for Android 6.0+ devices. To grant permissions in runtime, you might use [PermissionAndroid API](https://facebook.github.io/react-native/docs/permissionsandroid.html).
168
 
176
 
169
 - To send a form data, the `Content-Type` header does not matter. When the body is an `Array` we will set proper content type for you.
177
 - To send a form data, the `Content-Type` header does not matter. When the body is an `Array` we will set proper content type for you.
170
 - To send binary data, you have two choices, use BASE64 encoded string or path points to a file contains the body.
178
 - To send binary data, you have two choices, use BASE64 encoded string or path points to a file contains the body.
171
- - If the `Content-Type` containing substring`;BASE64` or `application/octet` the given body will be considered as a BASE64 encoded data which will be decoded to binary data as the request body.   
179
+ - If the `Content-Type` containing substring`;BASE64` or `application/octet` the given body will be considered as a BASE64 encoded data which will be decoded to binary data as the request body.
172
  - Otherwise, if a string starts with `RNFetchBlob-file://` (which can simply be done by `RNFetchBlob.wrap(PATH_TO_THE_FILE)`), it will try to find the data from the URI string after `RNFetchBlob-file://` and use it as the request body.
180
  - Otherwise, if a string starts with `RNFetchBlob-file://` (which can simply be done by `RNFetchBlob.wrap(PATH_TO_THE_FILE)`), it will try to find the data from the URI string after `RNFetchBlob-file://` and use it as the request body.
173
 - To send the body as-is, simply use a `Content-Type` header not containing `;BASE64` or `application/octet`.
181
 - To send the body as-is, simply use a `Content-Type` header not containing `;BASE64` or `application/octet`.
174
 
182
 
189
   })
197
   })
190
   .then((res) => {
198
   .then((res) => {
191
     let status = res.info().status;
199
     let status = res.info().status;
192
-    
200
+
193
     if(status == 200) {
201
     if(status == 200) {
194
       // the conversion is done in native code
202
       // the conversion is done in native code
195
       let base64Str = res.base64()
203
       let base64Str = res.base64()
290
     'Content-Type' : 'application/octet-stream',
298
     'Content-Type' : 'application/octet-stream',
291
     // here's the body you're going to send, should be a BASE64 encoded string
299
     // here's the body you're going to send, should be a BASE64 encoded string
292
     // (you can use "base64"(refer to the library 'mathiasbynens/base64') APIs to make one).
300
     // (you can use "base64"(refer to the library 'mathiasbynens/base64') APIs to make one).
293
-    // The data will be converted to "byte array"(say, blob) before request sent.  
301
+    // The data will be converted to "byte array"(say, blob) before request sent.
294
   }, base64ImageString)
302
   }, base64ImageString)
295
   .then((res) => {
303
   .then((res) => {
296
     console.log(res.text())
304
     console.log(res.text())
648
     ifstream.onError((err) => {
656
     ifstream.onError((err) => {
649
       console.log('oops', err)
657
       console.log('oops', err)
650
     })
658
     })
651
-    ifstream.onEnd(() => {  
659
+    ifstream.onEnd(() => {
652
       <Image source={{ uri : 'data:image/png,base64' + data }}
660
       <Image source={{ uri : 'data:image/png,base64' + data }}
653
     })
661
     })
654
 })
662
 })
673
 .catch(console.error)
681
 .catch(console.error)
674
 ```
682
 ```
675
 
683
 
676
-or 
684
+or
677
 
685
 
678
 ```js
686
 ```js
679
 RNFetchBlob.fs.writeStream(
687
 RNFetchBlob.fs.writeStream(
749
   .then((res) => {
757
   .then((res) => {
750
     // set session of a response
758
     // set session of a response
751
     res.session('foo')
759
     res.session('foo')
752
-  })  
760
+  })
753
 
761
 
754
   RNFetchblob.config({
762
   RNFetchblob.config({
755
     // you can also set session beforehand
763
     // you can also set session beforehand
759
   .fetch('GET', 'http://example.com/download/file')
767
   .fetch('GET', 'http://example.com/download/file')
760
   .then((res) => {
768
   .then((res) => {
761
     // ...
769
     // ...
762
-  })  
770
+  })
763
 
771
 
764
   // or put an existing file path to the session
772
   // or put an existing file path to the session
765
   RNFetchBlob.session('foo').add('some-file-path')
773
   RNFetchBlob.session('foo').add('some-file-path')
794
 })
802
 })
795
 ```
803
 ```
796
 
804
 
805
+### WiFi only requests
806
+
807
+If you wish to only route requests through the Wifi interface, set the below configuration.
808
+Note: On Android, the `ACCESS_NETWORK_STATE` permission must be set, and this flag will only work
809
+on API version 21 (Lollipop, Android 5.0) or above. APIs below 21 will ignore this flag.
810
+
811
+```js
812
+RNFetchBlob.config({
813
+  wifiOnly : true
814
+})
815
+.fetch('GET', 'https://mysite.com')
816
+.then((resp) => {
817
+  // ...
818
+})
819
+```
820
+
797
 ## Web API Polyfills
821
 ## Web API Polyfills
798
 
822
 
799
 After `0.8.0` we've made some [Web API polyfills](https://github.com/joltup/rn-fetch-blob/wiki/Web-API-Polyfills-(experimental)) that makes some browser-based library available in RN.
823
 After `0.8.0` we've made some [Web API polyfills](https://github.com/joltup/rn-fetch-blob/wiki/Web-API-Polyfills-(experimental)) that makes some browser-based library available in RN.

+ 2
- 0
android/src/main/java/com/RNFetchBlob/RNFetchBlobConfig.java View File

10
     public String appendExt;
10
     public String appendExt;
11
     public ReadableMap addAndroidDownloads;
11
     public ReadableMap addAndroidDownloads;
12
     public Boolean trusty;
12
     public Boolean trusty;
13
+    public Boolean wifiOnly = false;
13
     public String key;
14
     public String key;
14
     public String mime;
15
     public String mime;
15
     public Boolean auto;
16
     public Boolean auto;
26
         this.path = options.hasKey("path") ? options.getString("path") : null;
27
         this.path = options.hasKey("path") ? options.getString("path") : null;
27
         this.appendExt = options.hasKey("appendExt") ? options.getString("appendExt") : "";
28
         this.appendExt = options.hasKey("appendExt") ? options.getString("appendExt") : "";
28
         this.trusty = options.hasKey("trusty") ? options.getBoolean("trusty") : false;
29
         this.trusty = options.hasKey("trusty") ? options.getBoolean("trusty") : false;
30
+        this.wifiOnly = options.hasKey("wifiOnly") ? options.getBoolean("wifiOnly") : false;
29
         if(options.hasKey("addAndroidDownloads")) {
31
         if(options.hasKey("addAndroidDownloads")) {
30
             this.addAndroidDownloads = options.getMap("addAndroidDownloads");
32
             this.addAndroidDownloads = options.getMap("addAndroidDownloads");
31
         }
33
         }

+ 46
- 13
android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java View File

9
 import android.net.Uri;
9
 import android.net.Uri;
10
 import android.os.Build;
10
 import android.os.Build;
11
 import androidx.annotation.NonNull;
11
 import androidx.annotation.NonNull;
12
+import android.net.Network;
13
+import android.net.NetworkCapabilities;
14
+import android.net.ConnectivityManager;
12
 import android.util.Base64;
15
 import android.util.Base64;
13
 
16
 
14
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
17
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
36
 import java.net.SocketException;
39
 import java.net.SocketException;
37
 import java.net.SocketTimeoutException;
40
 import java.net.SocketTimeoutException;
38
 import java.net.URL;
41
 import java.net.URL;
42
+import java.net.Proxy;
39
 import java.nio.ByteBuffer;
43
 import java.nio.ByteBuffer;
40
 import java.nio.charset.CharacterCodingException;
44
 import java.nio.charset.CharacterCodingException;
41
 import java.nio.charset.Charset;
45
 import java.nio.charset.Charset;
231
                 clientBuilder = client.newBuilder();
235
                 clientBuilder = client.newBuilder();
232
             }
236
             }
233
 
237
 
238
+            // wifi only, need ACCESS_NETWORK_STATE permission
239
+            // and API level >= 21
240
+            if(this.options.wifiOnly){
241
+
242
+                boolean found = false;
243
+
244
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
245
+                    ConnectivityManager connectivityManager = (ConnectivityManager) RNFetchBlob.RCTContext.getSystemService(RNFetchBlob.RCTContext.CONNECTIVITY_SERVICE);
246
+                    Network[] networks = connectivityManager.getAllNetworks();
247
+
248
+                    for (Network network : networks) {
249
+                        //NetworkInfo netInfo = connectivityManager.getNetworkInfo(network);
250
+                        NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(network);
251
+                        if(caps == null){
252
+                            continue;
253
+                        }
254
+
255
+                        // netinfo is deprecated
256
+                        //if (netInfo.getType() == ConnectivityManager.TYPE_WIFI && netInfo.getState() == NetworkInfo.State.CONNECTED) {
257
+                        if(caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){
258
+                            clientBuilder.proxy(Proxy.NO_PROXY);
259
+                            clientBuilder.socketFactory(network.getSocketFactory());
260
+                            found = true;
261
+                            break;
262
+
263
+                        }
264
+                    }
265
+
266
+                    if(!found){
267
+                        callback.invoke("No available WiFi connections.", null, null);
268
+                        releaseTaskResource();
269
+                        return;
270
+                    }
271
+                }
272
+                else{
273
+                    RNFetchBlobUtils.emitWarningEvent("RNFetchBlob: wifiOnly was set, but SDK < 21. wifiOnly was ignored.");
274
+                }
275
+            }
276
+
234
             final Request.Builder builder = new Request.Builder();
277
             final Request.Builder builder = new Request.Builder();
235
             try {
278
             try {
236
                 builder.url(new URL(url));
279
                 builder.url(new URL(url));
530
                 }
573
                 }
531
                 break;
574
                 break;
532
             case FileStorage:
575
             case FileStorage:
533
-                ResponseBody responseBody = resp.body();
534
-
535
                 try {
576
                 try {
536
                     // In order to write response data to `destPath` we have to invoke this method.
577
                     // In order to write response data to `destPath` we have to invoke this method.
537
                     // It uses customized response body which is able to report download progress
578
                     // It uses customized response body which is able to report download progress
538
                     // and write response data to destination path.
579
                     // and write response data to destination path.
539
-                    responseBody.bytes();
580
+                    resp.body().bytes();
540
                 } catch (Exception ignored) {
581
                 } catch (Exception ignored) {
541
 //                    ignored.printStackTrace();
582
 //                    ignored.printStackTrace();
542
                 }
583
                 }
543
-
544
-                RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
545
-
546
-                if(rnFetchBlobFileResp != null && rnFetchBlobFileResp.isDownloadComplete() == false){
547
-                    callback.invoke("RNFetchBlob failed. Download interrupted.", null);
548
-                }
549
-                else {
550
-                    this.destPath = this.destPath.replace("?append=true", "");
551
-                    callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
552
-                }
584
+                this.destPath = this.destPath.replace("?append=true", "");
585
+                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
553
                 break;
586
                 break;
554
             default:
587
             default:
555
                 try {
588
                 try {

+ 10
- 0
index.d.ts View File

546
      */
546
      */
547
     trusty?: boolean;
547
     trusty?: boolean;
548
 
548
 
549
+    /**
550
+     * Set this property to true will only do requests through the WiFi interface, and fail otherwise.
551
+     */
552
+    wifiOnly?: boolean;
553
+
554
+    /**
555
+     * Set this property so redirects are not automatically followed.
556
+     */
557
+    followRedirect?: boolean;
558
+
549
     /**
559
     /**
550
      * Set this property to true will makes response data of the fetch stored in a temp file, by default the temp
560
      * Set this property to true will makes response data of the fetch stored in a temp file, by default the temp
551
      * file will stored in App's own root folder with file name template RNFetchBlob_tmp${timestamp}.
561
      * file will stored in App's own root folder with file name template RNFetchBlob_tmp${timestamp}.

+ 6
- 0
index.js View File

105
  *                   If it doesn't exist, the file is downloaded as usual
105
  *                   If it doesn't exist, the file is downloaded as usual
106
  *         @property {number} timeout
106
  *         @property {number} timeout
107
  *                   Request timeout in millionseconds, by default it's 30000ms.
107
  *                   Request timeout in millionseconds, by default it's 30000ms.
108
+ *         @property {boolean} followRedirect
109
+ *                   Follow redirects automatically, default true
110
+ *         @property {boolean} trusty
111
+ *                   Trust all certificates
112
+ *         @property {boolean} wifiOnly
113
+ *                   Only do requests through WiFi. Android SDK 21 or above only.
108
  *
114
  *
109
  * @return {function} This method returns a `fetch` method instance.
115
  * @return {function} This method returns a `fetch` method instance.
110
  */
116
  */

+ 3
- 1
index.js.flow View File

163
   path?: string,
163
   path?: string,
164
   session?: string,
164
   session?: string,
165
   timeout?: number,
165
   timeout?: number,
166
-  trusty?: boolean
166
+  trusty?: boolean,
167
+  wifiOnly?: boolean,
168
+  followRedirect?: boolean
167
 };
169
 };
168
 export type RNFetchBlobResponseInfo = {
170
 export type RNFetchBlobResponseInfo = {
169
   headers: {[fieldName: string]: string},
171
   headers: {[fieldName: string]: string},

+ 1
- 0
ios/RNFetchBlobConst.h View File

32
 extern NSString *const CONFIG_FILE_PATH;
32
 extern NSString *const CONFIG_FILE_PATH;
33
 extern NSString *const CONFIG_FILE_EXT;
33
 extern NSString *const CONFIG_FILE_EXT;
34
 extern NSString *const CONFIG_TRUSTY;
34
 extern NSString *const CONFIG_TRUSTY;
35
+extern NSString *const CONFIG_WIFI_ONLY;
35
 extern NSString *const CONFIG_INDICATOR;
36
 extern NSString *const CONFIG_INDICATOR;
36
 extern NSString *const CONFIG_KEY;
37
 extern NSString *const CONFIG_KEY;
37
 extern NSString *const CONFIG_EXTRA_BLOB_CTYPE;
38
 extern NSString *const CONFIG_EXTRA_BLOB_CTYPE;

+ 1
- 0
ios/RNFetchBlobConst.m View File

16
 NSString *const CONFIG_FILE_PATH = @"path";
16
 NSString *const CONFIG_FILE_PATH = @"path";
17
 NSString *const CONFIG_FILE_EXT = @"appendExt";
17
 NSString *const CONFIG_FILE_EXT = @"appendExt";
18
 NSString *const CONFIG_TRUSTY = @"trusty";
18
 NSString *const CONFIG_TRUSTY = @"trusty";
19
+NSString *const CONFIG_WIFI_ONLY = @"wifiOnly";
19
 NSString *const CONFIG_INDICATOR = @"indicator";
20
 NSString *const CONFIG_INDICATOR = @"indicator";
20
 NSString *const CONFIG_KEY = @"key";
21
 NSString *const CONFIG_KEY = @"key";
21
 NSString *const CONFIG_EXTRA_BLOB_CTYPE = @"binaryContentTypes";
22
 NSString *const CONFIG_EXTRA_BLOB_CTYPE = @"binaryContentTypes";

+ 4
- 0
ios/RNFetchBlobRequest.m View File

124
         defaultConfigObject.timeoutIntervalForRequest = timeout/1000;
124
         defaultConfigObject.timeoutIntervalForRequest = timeout/1000;
125
     }
125
     }
126
     
126
     
127
+    if([options valueForKey:CONFIG_WIFI_ONLY] != nil && ![options[CONFIG_WIFI_ONLY] boolValue]){
128
+        [defaultConfigObject setAllowsCellularAccess:NO];
129
+    }
130
+    
127
     defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
131
     defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
128
     session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:operationQueue];
132
     session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:operationQueue];
129
     
133
     

+ 4
- 1
types.js View File

5
   appendExt : string,
5
   appendExt : string,
6
   session : string,
6
   session : string,
7
   addAndroidDownloads : any,
7
   addAndroidDownloads : any,
8
-  indicator : bool
8
+  indicator : bool,
9
+  followRedirect : bool,
10
+  trusty : bool,
11
+  wifiOnly : bool
9
 };
12
 };
10
 
13
 
11
 type RNFetchBlobNative = {
14
 type RNFetchBlobNative = {