Kaynağa Gözat

Add support of switch chunked transfer encoding #117

Ben Hsieh 8 yıl önce
ebeveyn
işleme
467788b8c4

+ 42
- 31
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobBody.java Dosyayı Görüntüle

@@ -34,42 +34,35 @@ public class RNFetchBlobBody extends RequestBody{
34 34
     RNFetchBlobReq.RequestType requestType;
35 35
     MediaType mime;
36 36
     File bodyCache;
37
+    Boolean chunkedEncoding = false;
37 38
 
38 39
 
39
-    /**
40
-     * Single file or raw content request constructor
41
-     * @param taskId
42
-     * @param type
43
-     * @param form
44
-     * @param contentType
45
-     */
46
-    public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, ReadableArray form, MediaType contentType) {
40
+    public RNFetchBlobBody(String taskId) {
47 41
         this.mTaskId = taskId;
48
-        this.form = form;
49
-        requestType = type;
50
-        mime = contentType;
51
-        try {
52
-            bodyCache = createMultipartBodyCache();
53
-            requestStream = new FileInputStream(bodyCache);
54
-            contentLength = bodyCache.length();
55
-        } catch(Exception ex) {
56
-            ex.printStackTrace();
57
-            RNFetchBlobUtils.emitWarningEvent("RNFetchBlob failed to create request multipart body :" + ex.getLocalizedMessage());
58
-        }
42
+    }
43
+
44
+    RNFetchBlobBody chunkedEncoding(boolean val) {
45
+        this.chunkedEncoding = val;
46
+        return this;
47
+    }
48
+
49
+    RNFetchBlobBody setMIME(MediaType mime) {
50
+        this.mime = mime;
51
+        return this;
52
+    }
53
+
54
+    RNFetchBlobBody setRequestType( RNFetchBlobReq.RequestType type) {
55
+        this.requestType = type;
56
+        return this;
59 57
     }
60 58
 
61 59
     /**
62
-     * Multipart request constructor
63
-     * @param taskId
64
-     * @param type
65
-     * @param rawBody
66
-     * @param contentType
60
+     * Set request body
61
+     * @param body A string represents the request body
62
+     * @return object itself
67 63
      */
68
-    public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, String rawBody, MediaType contentType) {
69
-        this.mTaskId = taskId;
70
-        requestType = type;
71
-        this.rawBody = rawBody;
72
-        mime = contentType;
64
+    RNFetchBlobBody setBody(String body) {
65
+        this.rawBody = body;
73 66
         if(rawBody == null) {
74 67
             this.rawBody = "";
75 68
             requestType = RNFetchBlobReq.RequestType.AsIs;
@@ -90,19 +83,37 @@ public class RNFetchBlobBody extends RequestBody{
90 83
             ex.printStackTrace();
91 84
             RNFetchBlobUtils.emitWarningEvent("RNFetchBlob failed to create single content request body :" + ex.getLocalizedMessage() + "\r\n");
92 85
         }
86
+        return this;
87
+    }
93 88
 
89
+    /**
90
+     * Set request body (Array)
91
+     * @param body A Readable array contains form data
92
+     * @return object itself
93
+     */
94
+    RNFetchBlobBody setBody(ReadableArray body) {
95
+        this.form = body;
96
+        try {
97
+            bodyCache = createMultipartBodyCache();
98
+            requestStream = new FileInputStream(bodyCache);
99
+            contentLength = bodyCache.length();
100
+        } catch(Exception ex) {
101
+            ex.printStackTrace();
102
+            RNFetchBlobUtils.emitWarningEvent("RNFetchBlob failed to create request multipart body :" + ex.getLocalizedMessage());
103
+        }
104
+        return this;
94 105
     }
95 106
 
96 107
     @Override
97 108
     public long contentLength() {
98
-        return contentLength;
109
+        return chunkedEncoding ? -1 : contentLength;
99 110
     }
100 111
 
101 112
     @Override
102 113
     public MediaType contentType() {
103 114
         return mime;
104 115
     }
105
-    
116
+
106 117
     @Override
107 118
     public void writeTo(BufferedSink sink) {
108 119
         try {

+ 32
- 49
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java Dosyayı Görüntüle

@@ -17,7 +17,6 @@ import com.facebook.react.bridge.ReactApplicationContext;
17 17
 import com.facebook.react.bridge.ReadableArray;
18 18
 import com.facebook.react.bridge.ReadableMap;
19 19
 import com.facebook.react.bridge.ReadableMapKeySetIterator;
20
-import com.facebook.react.bridge.WritableArray;
21 20
 import com.facebook.react.bridge.WritableMap;
22 21
 import com.facebook.react.modules.core.DeviceEventManagerModule;
23 22
 
@@ -33,7 +32,6 @@ import java.nio.ByteBuffer;
33 32
 import java.nio.charset.CharacterCodingException;
34 33
 import java.nio.charset.Charset;
35 34
 import java.nio.charset.CharsetEncoder;
36
-import java.util.ArrayList;
37 35
 import java.util.HashMap;
38 36
 import java.util.concurrent.TimeUnit;
39 37
 
@@ -74,7 +72,6 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
74 72
 
75 73
     ReactApplicationContext ctx;
76 74
     RNFetchBlobConfig options;
77
-    ArrayList<String> redirects = new ArrayList<>();
78 75
     String taskId;
79 76
     String method;
80 77
     String url;
@@ -107,7 +104,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
107 104
             responseType = ResponseType.KeepInMemory;
108 105
 
109 106
 
110
-		if (body != null)
107
+        if (body != null)
111 108
             requestType = RequestType.SingleFile;
112 109
         else if (arrayBody != null)
113 110
             requestType = RequestType.Form;
@@ -159,21 +156,21 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
159 156
 
160 157
         // find cached result if `key` property exists
161 158
         String cacheKey = this.taskId;
162
-		String ext = this.options.appendExt.isEmpty() ? "." + this.options.appendExt : "";
159
+        String ext = this.options.appendExt.isEmpty() ? "." + this.options.appendExt : "";
163 160
 
164
-       	if (this.options.key != null) {
165
-           cacheKey = RNFetchBlobUtils.getMD5(this.options.key);
166
-           if (cacheKey == null) {
167
-               cacheKey = this.taskId;
168
-           }
161
+        if (this.options.key != null) {
162
+            cacheKey = RNFetchBlobUtils.getMD5(this.options.key);
163
+            if (cacheKey == null) {
164
+                cacheKey = this.taskId;
165
+            }
169 166
 
170
-           File file = new File(RNFetchBlobFS.getTmpPath(RNFetchBlob.RCTContext, cacheKey) + ext);
167
+            File file = new File(RNFetchBlobFS.getTmpPath(RNFetchBlob.RCTContext, cacheKey) + ext);
171 168
 
172
-           if (file.exists()) {
173
-               callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, file.getAbsolutePath());
174
-               return;
175
-           }
176
-       }
169
+            if (file.exists()) {
170
+                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, file.getAbsolutePath());
171
+                return;
172
+            }
173
+        }
177 174
 
178 175
         if(this.options.path != null)
179 176
             this.destPath = this.options.path;
@@ -239,35 +236,33 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
239 236
                 requestType = RequestType.WithoutBody;
240 237
             }
241 238
 
239
+            boolean isChunkedRequest = getHeaderIgnoreCases(mheaders, "Transfer-Encoding").equalsIgnoreCase("chunked");
242 240
 
243 241
             // set request body
244 242
             switch (requestType) {
245 243
                 case SingleFile:
246
-                    requestBody = new RNFetchBlobBody(
247
-                            taskId,
248
-                            requestType,
249
-                            rawRequestBody,
250
-                            MediaType.parse(getHeaderIgnoreCases(mheaders, "content-type"))
251
-                    );
244
+                    requestBody = new RNFetchBlobBody(taskId)
245
+                            .chunkedEncoding(isChunkedRequest)
246
+                            .setRequestType(requestType)
247
+                            .setBody(rawRequestBody)
248
+                            .setMIME(MediaType.parse(getHeaderIgnoreCases(mheaders, "content-type")));
252 249
                     builder.method(method, requestBody);
253 250
                     break;
254 251
                 case AsIs:
255
-                    requestBody = new RNFetchBlobBody(
256
-                            taskId,
257
-                            requestType,
258
-                            rawRequestBody,
259
-                            MediaType.parse(getHeaderIgnoreCases(mheaders, "content-type"))
260
-                    );
252
+                    requestBody = new RNFetchBlobBody(taskId)
253
+                            .chunkedEncoding(isChunkedRequest)
254
+                            .setRequestType(requestType)
255
+                            .setBody(rawRequestBody)
256
+                            .setMIME(MediaType.parse(getHeaderIgnoreCases(mheaders, "content-type")));
261 257
                     builder.method(method, requestBody);
262 258
                     break;
263 259
                 case Form:
264 260
                     String boundary = "RNFetchBlob-" + taskId;
265
-                    requestBody = new RNFetchBlobBody(
266
-                            taskId,
267
-                            requestType,
268
-                            rawRequestBodyArray,
269
-                            MediaType.parse("multipart/form-data; boundary="+ boundary)
270
-                    );
261
+                    requestBody = new RNFetchBlobBody(taskId)
262
+                            .chunkedEncoding(isChunkedRequest)
263
+                            .setRequestType(requestType)
264
+                            .setBody(rawRequestBodyArray)
265
+                            .setMIME(MediaType.parse("multipart/form-data; boundary="+ boundary));
271 266
                     builder.method(method, requestBody);
272 267
                     break;
273 268
 
@@ -283,15 +278,6 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
283 278
 
284 279
             final Request req = builder.build();
285 280
 
286
-            // intercept network redirections
287
-            clientBuilder.addNetworkInterceptor(new Interceptor() {
288
-                @Override
289
-                public Response intercept(Chain chain) throws IOException {
290
-                    redirects.add(chain.request().url().toString());
291
-                    return chain.proceed(chain.request());
292
-                }
293
-            });
294
-
295 281
             // Add request interceptor for upload progress event
296 282
             clientBuilder.addInterceptor(new Interceptor() {
297 283
                 @Override
@@ -468,7 +454,9 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
468 454
                     // It uses customized response body which is able to report download progress
469 455
                     // and write response data to destination path.
470 456
                     resp.body().bytes();
471
-                } catch (Exception ignored) {  }
457
+                } catch (Exception ignored) {
458
+                    ignored.printStackTrace();
459
+                }
472 460
                 callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
473 461
                 break;
474 462
             default:
@@ -521,11 +509,6 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
521 509
             headers.putString(resp.headers().name(i), resp.headers().value(i));
522 510
         }
523 511
         info.putMap("headers", headers);
524
-        WritableArray redirectList = Arguments.createArray();
525
-        for(String r : redirects) {
526
-            redirectList.pushString(r);
527
-        }
528
-        info.putArray("redirects", redirectList);
529 512
         Headers h = resp.headers();
530 513
         if(isBlobResp) {
531 514
             info.putString("respType", "blob");

+ 9
- 1
src/ios/RNFetchBlobReqBuilder.m Dosyayı Görüntüle

@@ -90,6 +90,7 @@
90 90
             // generate octet-stream body
91 91
             if(body != nil) {
92 92
                 __block NSString * cType = [[self class] getHeaderIgnoreCases:@"content-type" fromHeaders:mheaders];
93
+                __block NSString * transferEncoding = [[self class] getHeaderIgnoreCases:@"transfer-encoding" fromHeaders:mheaders];
93 94
                 // when headers does not contain a key named "content-type" (case ignored), use default content type
94 95
                 if(cType == nil)
95 96
                 {
@@ -111,7 +112,14 @@
111 112
                         return;
112 113
                     }
113 114
                     size = [[[NSFileManager defaultManager] attributesOfItemAtPath:orgPath error:nil] fileSize];
114
-                    [request setHTTPBodyStream: [NSInputStream inputStreamWithFileAtPath:orgPath ]];
115
+                    if(transferEncoding != nil && [[transferEncoding lowercaseString] isEqualToString:@"chunked"])
116
+                    {
117
+                        [request setHTTPBodyStream: [NSInputStream inputStreamWithFileAtPath:orgPath ]];
118
+                    }
119
+                    else
120
+                    {
121
+                        [request setHTTPBody:[NSData dataWithContentsOfFile:orgPath ]];
122
+                    }
115 123
                 }
116 124
                 // otherwise convert it as BASE64 data string
117 125
                 else {