Просмотр исходного кода

wifi only option, and missing typings.

Cristiano Coelho 5 лет назад
Родитель
Сommit
3bbe72daac

+ 35
- 11
README.md Просмотреть файл

@@ -41,7 +41,7 @@ rn-fetch-blob version 0.10.16 is only compatible with react native 0.60 and up.
41 41
 
42 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 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,8 +116,8 @@ If you're going to access external storage (say, SD card storage) for `Android 5
116 116
 
117 117
     <uses-permission android:name="android.permission.INTERNET" />
118 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 121
 +   <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
122 122
     ...
123 123
 
@@ -129,10 +129,18 @@ Also, if you're going to use `Android Download Manager` you have to add this to
129 129
     <intent-filter>
130 130
             <action android:name="android.intent.action.MAIN" />
131 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 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 144
 **Grant Access Permission for Android 6.0**
137 145
 
138 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,7 +176,7 @@ To sum up:
168 176
 
169 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 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 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 181
 - To send the body as-is, simply use a `Content-Type` header not containing `;BASE64` or `application/octet`.
174 182
 
@@ -189,7 +197,7 @@ RNFetchBlob.fetch('GET', 'http://www.example.com/images/img1.png', {
189 197
   })
190 198
   .then((res) => {
191 199
     let status = res.info().status;
192
-    
200
+
193 201
     if(status == 200) {
194 202
       // the conversion is done in native code
195 203
       let base64Str = res.base64()
@@ -290,7 +298,7 @@ RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
290 298
     'Content-Type' : 'application/octet-stream',
291 299
     // here's the body you're going to send, should be a BASE64 encoded string
292 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 302
   }, base64ImageString)
295 303
   .then((res) => {
296 304
     console.log(res.text())
@@ -648,7 +656,7 @@ RNFetchBlob.fs.readStream(
648 656
     ifstream.onError((err) => {
649 657
       console.log('oops', err)
650 658
     })
651
-    ifstream.onEnd(() => {  
659
+    ifstream.onEnd(() => {
652 660
       <Image source={{ uri : 'data:image/png,base64' + data }}
653 661
     })
654 662
 })
@@ -673,7 +681,7 @@ RNFetchBlob.fs.writeStream(
673 681
 .catch(console.error)
674 682
 ```
675 683
 
676
-or 
684
+or
677 685
 
678 686
 ```js
679 687
 RNFetchBlob.fs.writeStream(
@@ -749,7 +757,7 @@ You can also group requests by using `session` API and use `dispose` to remove t
749 757
   .then((res) => {
750 758
     // set session of a response
751 759
     res.session('foo')
752
-  })  
760
+  })
753 761
 
754 762
   RNFetchblob.config({
755 763
     // you can also set session beforehand
@@ -759,7 +767,7 @@ You can also group requests by using `session` API and use `dispose` to remove t
759 767
   .fetch('GET', 'http://example.com/download/file')
760 768
   .then((res) => {
761 769
     // ...
762
-  })  
770
+  })
763 771
 
764 772
   // or put an existing file path to the session
765 773
   RNFetchBlob.session('foo').add('some-file-path')
@@ -794,6 +802,22 @@ RNFetchBlob.config({
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 821
 ## Web API Polyfills
798 822
 
799 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 Просмотреть файл

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

+ 46
- 13
android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java Просмотреть файл

@@ -9,6 +9,9 @@ import android.database.Cursor;
9 9
 import android.net.Uri;
10 10
 import android.os.Build;
11 11
 import androidx.annotation.NonNull;
12
+import android.net.Network;
13
+import android.net.NetworkCapabilities;
14
+import android.net.ConnectivityManager;
12 15
 import android.util.Base64;
13 16
 
14 17
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
@@ -36,6 +39,7 @@ import java.net.MalformedURLException;
36 39
 import java.net.SocketException;
37 40
 import java.net.SocketTimeoutException;
38 41
 import java.net.URL;
42
+import java.net.Proxy;
39 43
 import java.nio.ByteBuffer;
40 44
 import java.nio.charset.CharacterCodingException;
41 45
 import java.nio.charset.Charset;
@@ -231,6 +235,45 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
231 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 277
             final Request.Builder builder = new Request.Builder();
235 278
             try {
236 279
                 builder.url(new URL(url));
@@ -530,26 +573,16 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
530 573
                 }
531 574
                 break;
532 575
             case FileStorage:
533
-                ResponseBody responseBody = resp.body();
534
-
535 576
                 try {
536 577
                     // In order to write response data to `destPath` we have to invoke this method.
537 578
                     // It uses customized response body which is able to report download progress
538 579
                     // and write response data to destination path.
539
-                    responseBody.bytes();
580
+                    resp.body().bytes();
540 581
                 } catch (Exception ignored) {
541 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 586
                 break;
554 587
             default:
555 588
                 try {

+ 10
- 0
index.d.ts Просмотреть файл

@@ -546,6 +546,16 @@ export interface RNFetchBlobConfig {
546 546
      */
547 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 560
      * Set this property to true will makes response data of the fetch stored in a temp file, by default the temp
551 561
      * file will stored in App's own root folder with file name template RNFetchBlob_tmp${timestamp}.

+ 6
- 0
index.js Просмотреть файл

@@ -105,6 +105,12 @@ function wrap(path:string):string {
105 105
  *                   If it doesn't exist, the file is downloaded as usual
106 106
  *         @property {number} timeout
107 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 115
  * @return {function} This method returns a `fetch` method instance.
110 116
  */

+ 3
- 1
index.js.flow Просмотреть файл

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

+ 1
- 0
ios/RNFetchBlobConst.h Просмотреть файл

@@ -32,6 +32,7 @@ extern NSString *const CONFIG_USE_TEMP;
32 32
 extern NSString *const CONFIG_FILE_PATH;
33 33
 extern NSString *const CONFIG_FILE_EXT;
34 34
 extern NSString *const CONFIG_TRUSTY;
35
+extern NSString *const CONFIG_WIFI_ONLY;
35 36
 extern NSString *const CONFIG_INDICATOR;
36 37
 extern NSString *const CONFIG_KEY;
37 38
 extern NSString *const CONFIG_EXTRA_BLOB_CTYPE;

+ 1
- 0
ios/RNFetchBlobConst.m Просмотреть файл

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

+ 4
- 0
ios/RNFetchBlobRequest.m Просмотреть файл

@@ -124,6 +124,10 @@ typedef NS_ENUM(NSUInteger, ResponseFormat) {
124 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 131
     defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
128 132
     session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:operationQueue];
129 133
     

+ 4
- 1
types.js Просмотреть файл

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