Browse Source

wip commit, complete Android form upload

Ben Hsieh 8 years ago
parent
commit
622c588ff4

+ 0
- 1
src/android/build.gradle View File

34
 
34
 
35
 dependencies {
35
 dependencies {
36
     compile 'com.facebook.react:react-native:+'
36
     compile 'com.facebook.react:react-native:+'
37
-    compile 'com.loopj.android:android-async-http:1.4.9'
38
     compile 'com.squareup.okhttp3:okhttp:3.4.1'
37
     compile 'com.squareup.okhttp3:okhttp:3.4.1'
39
 }
38
 }

+ 196
- 17
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobBody.java View File

1
 package com.RNFetchBlob;
1
 package com.RNFetchBlob;
2
 
2
 
3
+import android.util.Base64;
4
+
3
 import com.facebook.react.bridge.Arguments;
5
 import com.facebook.react.bridge.Arguments;
6
+import com.facebook.react.bridge.ReactApplicationContext;
7
+import com.facebook.react.bridge.ReadableArray;
8
+import com.facebook.react.bridge.ReadableMap;
9
+import com.facebook.react.bridge.WritableArray;
4
 import com.facebook.react.bridge.WritableMap;
10
 import com.facebook.react.bridge.WritableMap;
5
 import com.facebook.react.modules.core.DeviceEventManagerModule;
11
 import com.facebook.react.modules.core.DeviceEventManagerModule;
6
 
12
 
13
+import java.io.File;
14
+import java.io.FileInputStream;
7
 import java.io.IOException;
15
 import java.io.IOException;
8
 import java.io.InputStream;
16
 import java.io.InputStream;
17
+import java.util.ArrayList;
18
+import java.util.HashMap;
9
 
19
 
10
 import okhttp3.MediaType;
20
 import okhttp3.MediaType;
11
 import okhttp3.RequestBody;
21
 import okhttp3.RequestBody;
12
 import okio.Buffer;
22
 import okio.Buffer;
13
 import okio.BufferedSink;
23
 import okio.BufferedSink;
24
+import okio.ByteString;
14
 import okio.ForwardingSink;
25
 import okio.ForwardingSink;
15
 import okio.Okio;
26
 import okio.Okio;
16
 import okio.Sink;
27
 import okio.Sink;
17
 
28
 
18
 /**
29
 /**
19
- * Created by wkh237on 2016/7/11.
30
+ * Created by wkh237 on 2016/7/11.
20
  */
31
  */
21
 public class RNFetchBlobBody extends RequestBody{
32
 public class RNFetchBlobBody extends RequestBody{
22
 
33
 
23
     InputStream requestStream;
34
     InputStream requestStream;
24
     long contentLength;
35
     long contentLength;
25
-    RequestBody originalBody;
36
+    long bytesWritten = 0;
37
+    ReadableArray form;
26
     String mTaskId;
38
     String mTaskId;
27
     RNFetchBlobReq.RequestType requestType;
39
     RNFetchBlobReq.RequestType requestType;
40
+    MediaType mime;
28
 
41
 
29
-    public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, RequestBody body, InputStream stream, long size) {
42
+    public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, ReadableArray form, InputStream stream, long size, MediaType contentType) {
30
         this.mTaskId = taskId;
43
         this.mTaskId = taskId;
31
-        originalBody = body;
44
+        this.form = form;
32
         requestStream = stream;
45
         requestStream = stream;
33
         contentLength = size;
46
         contentLength = size;
34
         requestType = type;
47
         requestType = type;
48
+        mime = contentType;
35
     }
49
     }
36
 
50
 
37
     @Override
51
     @Override
38
     public MediaType contentType() {
52
     public MediaType contentType() {
39
-        return originalBody.contentType();
53
+        return mime;
40
     }
54
     }
41
 
55
 
42
     @Override
56
     @Override
46
         BufferedSink buffer = Okio.buffer(source);
60
         BufferedSink buffer = Okio.buffer(source);
47
         switch (requestType) {
61
         switch (requestType) {
48
             case Form:
62
             case Form:
49
-                originalBody.writeTo(buffer);
50
-                break;
51
-            case SingleFile:
52
-                byte [] chunk = new byte[10240];
53
-                int cursor = requestStream.read(chunk, 0, 10240);
54
-                while(cursor > 0) {
55
-                    cursor = requestStream.read(chunk, 0, 10240);
56
-                    buffer.write(chunk);
63
+                String boundary = "RNFetchBlob-" + mTaskId;
64
+                ArrayList<FormField> fields = countFormDataLength();
65
+                ReactApplicationContext ctx = RNFetchBlob.RCTContext;
66
+                for(int i = 0;i < fields.size(); i++) {
67
+                    FormField field = fields.get(i);
68
+                    String data = field.data;
69
+                    String name = field.name;
70
+                    // skip invalid fields
71
+                    if(name == null || data == null)
72
+                        continue;
73
+                    // form begin
74
+                    String header = "--" + boundary + "\r\n";
75
+                    if (field.filename != null) {
76
+                        header += "Content-Disposition: form-data; name=" + name + "; filename=" + field.filename + "\r\n";
77
+                        header += "Content-Type: " + field.mime+ "\r\n\r\n";
78
+                        sink.write(header.getBytes());
79
+                        // file field header end
80
+                        // upload from storage
81
+                        if (data.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
82
+                            String orgPath = data.substring(RNFetchBlobConst.FILE_PREFIX.length());
83
+                            orgPath = RNFetchBlobFS.normalizePath(orgPath);
84
+                            // path starts with content://
85
+                            if (RNFetchBlobFS.isAsset(orgPath)) {
86
+                                try {
87
+                                    String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
88
+                                    InputStream in = ctx.getAssets().open(assetName);
89
+                                    pipeStreamToSink(in, sink);
90
+                                } catch (IOException e) {
91
+
92
+                                }
93
+                            }
94
+                            // data from normal files
95
+                            else {
96
+                                File file = new File(RNFetchBlobFS.normalizePath(orgPath));
97
+                                if(file.exists()) {
98
+                                    FileInputStream fs = new FileInputStream(file);
99
+                                    pipeStreamToSink(fs, sink);
100
+                                }
101
+                            }
102
+                        }
103
+                        // base64 embedded file content
104
+                        else {
105
+                            byte[] b = Base64.decode(data, 0);
106
+                            sink.write(b);
107
+                            bytesWritten += b.length;
108
+                            emitUploadProgress(bytesWritten, contentLength);
109
+                        }
110
+
111
+                    }
112
+                    // data field
113
+                    else {
114
+                        header += "Content-Disposition: form-data; name=" + name + "\r\n";
115
+                        header += "Content-Type: " + field.mime + "\r\n\r\n";
116
+                        sink.write(header.getBytes());
117
+                        byte[] fieldData = field.data.getBytes();
118
+                        bytesWritten += fieldData.length;
119
+                        sink.write(fieldData);
120
+                    }
121
+                    // form end
122
+                    sink.write("\r\n".getBytes());
57
                 }
123
                 }
58
-                requestStream.close();
124
+                // close the form
125
+                byte[] end = ("--" + boundary + "--\r\n").getBytes();
126
+                sink.write(end);
59
                 break;
127
                 break;
60
-            case Others:
61
-                originalBody.writeTo(buffer);
128
+            case SingleFile:
129
+                pipeStreamToSink(requestStream, sink);
130
+//                byte [] chunk = new byte[10240];
131
+//                int read = requestStream.read(chunk, 0, 10240);
132
+//                sink.write(chunk, 0, read);
133
+//                bytesWritten += read;
134
+//                while(read > 0) {
135
+//                    read = requestStream.read(chunk, 0, 10240);
136
+//                    if(read > 0) {
137
+//                        sink.write(chunk, 0, read);
138
+//                        bytesWritten += read;
139
+//                        emitUploadProgress(bytesWritten, contentLength);
140
+//                    }
141
+//
142
+//                }
143
+//                requestStream.close();
62
                 break;
144
                 break;
63
         }
145
         }
64
         buffer.flush();
146
         buffer.flush();
65
     }
147
     }
66
 
148
 
149
+    private void pipeStreamToSink(InputStream stream, BufferedSink sink) throws IOException {
150
+        byte [] chunk = new byte[10240];
151
+        int read = stream.read(chunk, 0, 10240);
152
+        sink.write(chunk, 0, read);
153
+        bytesWritten += read;
154
+        while(read > 0) {
155
+            read = stream.read(chunk, 0, 10240);
156
+            if(read > 0) {
157
+                sink.write(chunk, 0, read);
158
+                bytesWritten += read;
159
+                emitUploadProgress(bytesWritten, contentLength);
160
+            }
161
+
162
+        }
163
+        stream.close();
164
+    }
165
+
166
+    private void emitUploadProgress(long current, long total) {
167
+        WritableMap args = Arguments.createMap();
168
+        args.putString("taskId", mTaskId);
169
+        args.putString("written", String.valueOf(bytesWritten));
170
+        args.putString("total", String.valueOf(contentLength));
171
+
172
+        // emit event to js context
173
+        RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
174
+                .emit(RNFetchBlobConst.EVENT_UPLOAD_PROGRESS, args);
175
+    }
176
+
177
+    /**
178
+     * Compute a proximate content length for form data
179
+     * @return
180
+     */
181
+    private ArrayList<FormField> countFormDataLength() {
182
+        long total = 0;
183
+        ArrayList<FormField> list = new ArrayList<>();
184
+        ReactApplicationContext ctx = RNFetchBlob.RCTContext;
185
+        for(int i = 0;i < form.size(); i++) {
186
+            ReadableMap field = form.getMap(i);
187
+            list.add(new FormField(field));
188
+            String data = field.getString("data");
189
+            if (field.hasKey("filename")) {
190
+                // upload from storage
191
+                if (data.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
192
+                    String orgPath = data.substring(RNFetchBlobConst.FILE_PREFIX.length());
193
+                    orgPath = RNFetchBlobFS.normalizePath(orgPath);
194
+                    // path starts with content://
195
+                    if (RNFetchBlobFS.isAsset(orgPath)) {
196
+                        try {
197
+                            String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
198
+                            long length = ctx.getAssets().openFd(assetName).getLength();
199
+                            total += length;
200
+                        } catch (IOException e) {
201
+
202
+                        }
203
+                    } else {
204
+                        File file = new File(RNFetchBlobFS.normalizePath(orgPath));
205
+                        total += file.length();
206
+                    }
207
+                }
208
+                // base64 embedded file content
209
+                else {
210
+                    byte[] bytes = Base64.decode(data, 0);
211
+                    total += bytes.length;
212
+                }
213
+            }
214
+            // data field
215
+            else {
216
+                total += field.getString("data").length();
217
+            }
218
+        }
219
+        contentLength = total;
220
+        return list;
221
+    }
222
+
223
+    private class FormField {
224
+        public String name;
225
+        public String filename;
226
+        public String mime;
227
+        public String data;
228
+
229
+        public FormField(ReadableMap rawData) {
230
+            if(rawData.hasKey("name"))
231
+                name = rawData.getString("name");
232
+            if(rawData.hasKey("filename"))
233
+                filename = rawData.getString("filename");
234
+            if(rawData.hasKey("type"))
235
+                mime = rawData.getString("type");
236
+            else {
237
+                mime = filename == null ? "text/plain" : "application/octet-stream";
238
+            }
239
+            if(rawData.hasKey("data"))
240
+                data = rawData.getString("data");
241
+        }
242
+    }
243
+
67
     private final class ProgressReportingSource extends ForwardingSink {
244
     private final class ProgressReportingSource extends ForwardingSink {
68
 
245
 
69
         private long bytesWritten = 0;
246
         private long bytesWritten = 0;
70
         private String mTaskId;
247
         private String mTaskId;
71
         private long mContentLength ;
248
         private long mContentLength ;
249
+        private Sink delegate;
72
 
250
 
73
         public ProgressReportingSource (Sink delegate, String taskId, long contentLength) {
251
         public ProgressReportingSource (Sink delegate, String taskId, long contentLength) {
74
             super(delegate);
252
             super(delegate);
75
             this.mTaskId = taskId;
253
             this.mTaskId = taskId;
76
             this.mContentLength = contentLength;
254
             this.mContentLength = contentLength;
255
+            this.delegate = delegate;
77
         }
256
         }
78
 
257
 
79
         @Override
258
         @Override
80
         public void write(Buffer source, long byteCount) throws IOException {
259
         public void write(Buffer source, long byteCount) throws IOException {
81
-            super.write(source, byteCount);
260
+            delegate.write(source, byteCount);
82
             // on progress, emit RNFetchBlobProgress upload progress event with ticketId,
261
             // on progress, emit RNFetchBlobProgress upload progress event with ticketId,
83
             // bytesWritten, and totalSize
262
             // bytesWritten, and totalSize
84
             bytesWritten += byteCount;
263
             bytesWritten += byteCount;

+ 3
- 3
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java View File

8
 import android.os.AsyncTask;
8
 import android.os.AsyncTask;
9
 import android.os.Environment;
9
 import android.os.Environment;
10
 import android.provider.MediaStore;
10
 import android.provider.MediaStore;
11
+import android.util.Base64;
11
 
12
 
12
 import com.facebook.react.bridge.Arguments;
13
 import com.facebook.react.bridge.Arguments;
13
 import com.facebook.react.bridge.Callback;
14
 import com.facebook.react.bridge.Callback;
17
 import com.facebook.react.bridge.WritableArray;
18
 import com.facebook.react.bridge.WritableArray;
18
 import com.facebook.react.bridge.WritableMap;
19
 import com.facebook.react.bridge.WritableMap;
19
 import com.facebook.react.modules.core.DeviceEventManagerModule;
20
 import com.facebook.react.modules.core.DeviceEventManagerModule;
20
-import com.loopj.android.http.Base64;
21
 
21
 
22
 import java.io.File;
22
 import java.io.File;
23
 import java.io.FileInputStream;
23
 import java.io.FileInputStream;
158
 
158
 
159
                     switch (encoding.toLowerCase()) {
159
                     switch (encoding.toLowerCase()) {
160
                         case "base64" :
160
                         case "base64" :
161
-                            promise.resolve(Base64.encodeToString(bytes, 0));
161
+                            promise.resolve(Base64.encodeToString(bytes, Base64.NO_WRAP));
162
                             break;
162
                             break;
163
                         case "ascii" :
163
                         case "ascii" :
164
                             WritableArray asciiResult = Arguments.createArray();
164
                             WritableArray asciiResult = Arguments.createArray();
700
             return data.getBytes(Charset.forName("US-ASCII"));
700
             return data.getBytes(Charset.forName("US-ASCII"));
701
         }
701
         }
702
         else if(encoding.equalsIgnoreCase("base64")) {
702
         else if(encoding.equalsIgnoreCase("base64")) {
703
-            return Base64.decode(data, 0);
703
+            return Base64.decode(data, Base64.NO_WRAP);
704
         }
704
         }
705
         else if(encoding.equalsIgnoreCase("utf8")) {
705
         else if(encoding.equalsIgnoreCase("utf8")) {
706
             return data.getBytes(Charset.forName("UTF-8"));
706
             return data.getBytes(Charset.forName("UTF-8"));

+ 100
- 101
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java View File

7
 import android.content.IntentFilter;
7
 import android.content.IntentFilter;
8
 import android.database.Cursor;
8
 import android.database.Cursor;
9
 import android.net.Uri;
9
 import android.net.Uri;
10
+import android.util.Base64;
10
 
11
 
11
-import com.RNFetchBlob.Request.FormPartBody;
12
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
12
 import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
13
 import com.RNFetchBlob.Response.RNFetchBlobFileResp;
13
 import com.RNFetchBlob.Response.RNFetchBlobFileResp;
14
 import com.facebook.react.bridge.Callback;
14
 import com.facebook.react.bridge.Callback;
16
 import com.facebook.react.bridge.ReadableArray;
16
 import com.facebook.react.bridge.ReadableArray;
17
 import com.facebook.react.bridge.ReadableMap;
17
 import com.facebook.react.bridge.ReadableMap;
18
 import com.facebook.react.bridge.ReadableMapKeySetIterator;
18
 import com.facebook.react.bridge.ReadableMapKeySetIterator;
19
-import com.loopj.android.http.Base64;
20
 
19
 
21
 import java.io.ByteArrayInputStream;
20
 import java.io.ByteArrayInputStream;
22
 import java.io.File;
21
 import java.io.File;
23
 import java.io.FileInputStream;
22
 import java.io.FileInputStream;
24
 import java.io.FileNotFoundException;
23
 import java.io.FileNotFoundException;
24
+import java.io.FileOutputStream;
25
 import java.io.IOException;
25
 import java.io.IOException;
26
 import java.io.InputStream;
26
 import java.io.InputStream;
27
+import java.net.MalformedURLException;
28
+import java.net.URL;
27
 
29
 
28
 import okhttp3.Call;
30
 import okhttp3.Call;
29
 import okhttp3.Interceptor;
31
 import okhttp3.Interceptor;
33
 import okhttp3.Request;
35
 import okhttp3.Request;
34
 import okhttp3.RequestBody;
36
 import okhttp3.RequestBody;
35
 import okhttp3.Response;
37
 import okhttp3.Response;
38
+import okhttp3.ResponseBody;
36
 
39
 
37
 /**
40
 /**
38
  * Created by wkh237 on 2016/6/21.
41
  * Created by wkh237 on 2016/6/21.
42
     enum RequestType  {
45
     enum RequestType  {
43
         Form,
46
         Form,
44
         SingleFile,
47
         SingleFile,
48
+        WithoutBody,
45
         Others
49
         Others
46
     };
50
     };
47
 
51
 
48
     enum ResponseType {
52
     enum ResponseType {
49
-        MemoryCache,
50
-        FileCache
53
+        KeepInMemory,
54
+        FileStorage
51
     };
55
     };
52
 
56
 
53
     MediaType contentType = RNFetchBlobConst.MIME_OCTET;
57
     MediaType contentType = RNFetchBlobConst.MIME_OCTET;
76
         this.rawRequestBody = body;
80
         this.rawRequestBody = body;
77
         this.rawRequestBodyArray = arrayBody;
81
         this.rawRequestBodyArray = arrayBody;
78
 
82
 
79
-        if(this.options.fileCache != null || this.options.path != null)
80
-            responseType = ResponseType.FileCache;
83
+        if(this.options.fileCache == true || this.options.path != null)
84
+            responseType = ResponseType.FileStorage;
81
         else
85
         else
82
-            responseType = ResponseType.MemoryCache;
86
+            responseType = ResponseType.KeepInMemory;
83
 
87
 
84
         if (body != null)
88
         if (body != null)
85
             requestType = RequestType.SingleFile;
89
             requestType = RequestType.SingleFile;
86
         else if (arrayBody != null)
90
         else if (arrayBody != null)
87
             requestType = RequestType.Form;
91
             requestType = RequestType.Form;
88
         else
92
         else
89
-            requestType = RequestType.Others;
93
+            requestType = RequestType.WithoutBody;
90
     }
94
     }
91
 
95
 
92
     @Override
96
     @Override
122
 
126
 
123
         // find cached result if `key` property exists
127
         // find cached result if `key` property exists
124
         String cacheKey = this.taskId;
128
         String cacheKey = this.taskId;
125
-        if (this.options.key != null) {
126
-            cacheKey = RNFetchBlobUtils.getMD5(this.options.key);
127
-            if (cacheKey == null) {
128
-                cacheKey = this.taskId;
129
-            }
130
-
131
-            File file = new File(RNFetchBlobFS.getTmpPath(ctx, cacheKey));
132
-            if (file.exists()) {
133
-                callback.invoke(null, file.getAbsolutePath());
134
-                return;
135
-            }
136
-        }
129
+//        if (this.options.key != null) {
130
+//            cacheKey = RNFetchBlobUtils.getMD5(this.options.key);
131
+//            if (cacheKey == null) {
132
+//                cacheKey = this.taskId;
133
+//            }
134
+//
135
+//            File file = new File(RNFetchBlobFS.getTmpPath(ctx, cacheKey));
136
+//            if (file.exists()) {
137
+//                callback.invoke(null, file.getAbsolutePath());
138
+//                return;
139
+//            }
140
+//        }
137
 
141
 
138
         if(this.options.path != null)
142
         if(this.options.path != null)
139
-            destPath = this.options.path;
140
-        else if(this.options.fileCache)
141
-            destPath = RNFetchBlobFS.getTmpPath(RNFetchBlob.RCTContext, cacheKey);
143
+            this.destPath = this.options.path;
144
+        else if(this.options.fileCache == true)
145
+            this.destPath = RNFetchBlobFS.getTmpPath(RNFetchBlob.RCTContext, cacheKey);
142
 
146
 
143
-        OkHttpClient client;
144
-        try {
147
+        OkHttpClient.Builder client;
145
 
148
 
149
+//        try {
146
             // use trusty SSL socket
150
             // use trusty SSL socket
147
             if (this.options.trusty) {
151
             if (this.options.trusty) {
148
                 client = RNFetchBlobUtils.getUnsafeOkHttpClient();
152
                 client = RNFetchBlobUtils.getUnsafeOkHttpClient();
149
             } else {
153
             } else {
150
-                client = new OkHttpClient();
154
+                client = new OkHttpClient.Builder();
151
             }
155
             }
152
 
156
 
153
             final Request.Builder builder = new Request.Builder();
157
             final Request.Builder builder = new Request.Builder();
154
-
158
+            try {
159
+                builder.url(new URL(url));
160
+            } catch (MalformedURLException e) {
161
+                e.printStackTrace();
162
+            }
155
             // set headers
163
             // set headers
156
             if (headers != null) {
164
             if (headers != null) {
157
                 ReadableMapKeySetIterator it = headers.keySetIterator();
165
                 ReadableMapKeySetIterator it = headers.keySetIterator();
158
                 while (it.hasNextKey()) {
166
                 while (it.hasNextKey()) {
159
                     String key = it.nextKey();
167
                     String key = it.nextKey();
160
-                    builder.addHeader(key, headers.getString(key));
168
+                    String value = headers.getString(key);
169
+                    builder.header(key, value);
161
                 }
170
                 }
162
             }
171
             }
163
 
172
 
164
             // set request body
173
             // set request body
165
             switch (requestType) {
174
             switch (requestType) {
166
                 case SingleFile:
175
                 case SingleFile:
176
+                    InputStream dataStream= buildOctetBody(rawRequestBody);
167
                     builder.method(method, new RNFetchBlobBody(
177
                     builder.method(method, new RNFetchBlobBody(
168
                             taskId,
178
                             taskId,
169
                             RequestType.SingleFile,
179
                             RequestType.SingleFile,
170
                             null,
180
                             null,
171
-                            buildOctetBody(rawRequestBody),
172
-                            contentLength
181
+                            dataStream,
182
+                            contentLength,
183
+                            RNFetchBlobConst.MIME_OCTET
173
                     ));
184
                     ));
174
                     break;
185
                     break;
175
                 case Form:
186
                 case Form:
176
                     builder.method(method, new RNFetchBlobBody(
187
                     builder.method(method, new RNFetchBlobBody(
177
                             taskId,
188
                             taskId,
178
                             RequestType.Form,
189
                             RequestType.Form,
179
-                            buildFormBody(rawRequestBodyArray),
190
+                            rawRequestBodyArray,
180
                             null,
191
                             null,
181
-                            contentLength
182
-                    ));
183
-                case Others:
184
-                    builder.method(method, new RNFetchBlobBody(
185
-                            taskId,
186
-                            RequestType.Others,
187
-                            buildRawBody(rawRequestBody),
188
-                            null,
189
-                            contentLength
192
+                            0,
193
+                            MediaType.parse("multipart/form-data; boundary=RNFetchBlob-" + taskId)
190
                     ));
194
                     ));
191
                     break;
195
                     break;
196
+                case WithoutBody:
197
+                    builder.method(method, null);
198
+                    break;
192
             }
199
             }
193
 
200
 
194
             final Request req = builder.build();
201
             final Request req = builder.build();
195
 
202
 
196
-            // create response handler
197
-            client.networkInterceptors().add(new Interceptor() {
203
+//             create response handler
204
+            client.addInterceptor(new Interceptor() {
198
                 @Override
205
                 @Override
199
                 public Response intercept(Chain chain) throws IOException {
206
                 public Response intercept(Chain chain) throws IOException {
200
-                    Response originalResponse = chain.proceed(req);
201
-                    RNFetchBlobDefaultResp exetneded;
202
-                    switch (responseType) {
203
-                        case MemoryCache:
204
-                            exetneded = new RNFetchBlobDefaultResp(
205
-                                    RNFetchBlob.RCTContext,
206
-                                    taskId,
207
-                                    originalResponse.body());
208
-                            break;
209
-                        case FileCache:
210
-                            exetneded = new RNFetchBlobFileResp(
211
-                                    RNFetchBlob.RCTContext,
212
-                                    taskId,
213
-                                    originalResponse.body(),
214
-                                    destPath);
215
-                            break;
216
-                        default:
217
-                            exetneded = new RNFetchBlobDefaultResp(
218
-                                    RNFetchBlob.RCTContext,
219
-                                    taskId,
220
-                                    originalResponse.body());
221
-                            break;
222
-                    }
223
-                    return originalResponse.newBuilder().body(exetneded).build();
207
+                Response originalResponse = chain.proceed(req);
208
+                    ResponseBody extended;
209
+                switch (responseType) {
210
+                    case KeepInMemory:
211
+                        extended = new RNFetchBlobDefaultResp(
212
+                                RNFetchBlob.RCTContext,
213
+                                taskId,
214
+                                originalResponse.body());
215
+                        break;
216
+                    case FileStorage:
217
+                        extended = new RNFetchBlobFileResp(
218
+                                RNFetchBlob.RCTContext,
219
+                                taskId,
220
+                                originalResponse.body(),
221
+                                destPath);
222
+                        break;
223
+                    default:
224
+                        extended = new RNFetchBlobDefaultResp(
225
+                                RNFetchBlob.RCTContext,
226
+                                taskId,
227
+                                originalResponse.body());
228
+                        break;
229
+                }
230
+                return originalResponse.newBuilder().body(extended).build();
224
                 }
231
                 }
225
             });
232
             });
226
 
233
 
227
-            client.newCall(req).enqueue(new okhttp3.Callback() {
234
+            client.build().newCall(req).enqueue(new okhttp3.Callback() {
228
                 @Override
235
                 @Override
229
                 public void onFailure(Call call, IOException e) {
236
                 public void onFailure(Call call, IOException e) {
230
                     callback.invoke(e.getLocalizedMessage(), null);
237
                     callback.invoke(e.getLocalizedMessage(), null);
255
             });
262
             });
256
 
263
 
257
 
264
 
258
-        } catch (Exception error) {
259
-            callback.invoke("RNFetchBlob request error: " + error.getMessage() + error.getCause());
260
-        }
265
+//        } catch (Exception error) {
266
+//            error.printStackTrace();
267
+//            callback.invoke("RNFetchBlob request error: " + error.getMessage() + error.getCause());
268
+//        }
261
     }
269
     }
262
 
270
 
263
     /**
271
     /**
266
      */
274
      */
267
     private void done(Response resp) {
275
     private void done(Response resp) {
268
         switch (responseType) {
276
         switch (responseType) {
269
-            case MemoryCache:
277
+            case KeepInMemory:
270
                 try {
278
                 try {
271
-                    callback.invoke(null, android.util.Base64.encode(resp.body().bytes(), 0));
279
+                    byte [] b = resp.body().bytes();
280
+                    callback.invoke(null, android.util.Base64.encodeToString(b,Base64.NO_WRAP));
272
                 } catch (IOException e) {
281
                 } catch (IOException e) {
273
                     callback.invoke("RNFetchBlob failed to encode response data to BASE64 string.", null);
282
                     callback.invoke("RNFetchBlob failed to encode response data to BASE64 string.", null);
274
                 }
283
                 }
275
                 break;
284
                 break;
276
-            case FileCache:
277
-                callback.invoke(null, destPath);
285
+            case FileStorage:
286
+                // write chunk
287
+                try {
288
+                    resp.body().bytes();
289
+                } catch (IOException e) {
290
+                    e.printStackTrace();
291
+                }
292
+                callback.invoke(null, this.destPath);
278
                 break;
293
                 break;
279
             default:
294
             default:
280
                 try {
295
                 try {
294
     RequestBody buildRawBody(String body) {
309
     RequestBody buildRawBody(String body) {
295
         if(body != null) {
310
         if(body != null) {
296
             this.contentType = MediaType.parse(options.mime);
311
             this.contentType = MediaType.parse(options.mime);
297
-        }
298
-        return RequestBody.create(this.contentType, body);
299
-    }
300
-
301
-    /**
302
-     * When request body is a multipart form data, build a MultipartBody object.
303
-     * @param body Body in array format
304
-     * @return
305
-     */
306
-    MultipartBody buildFormBody(ReadableArray body) {
307
-        if (body != null && (method.equalsIgnoreCase("post") || method.equalsIgnoreCase("put"))) {
308
-            this.contentType = RNFetchBlobConst.MIME_MULTIPART;
309
-            MultipartBody.Builder formBuilder = new MultipartBody.Builder();
310
-            formBuilder.setType(MultipartBody.FORM);
311
-
312
-            for (int i = 0; i < body.size(); i++) {
313
-                ReadableMap map = body.getMap(i);
314
-                FormPartBody fieldData = new FormPartBody(RNFetchBlob.RCTContext, map);
315
-                if(fieldData.filename == null)
316
-                    formBuilder.addFormDataPart(fieldData.fieldName, fieldData.stringBody);
317
-                else
318
-                    formBuilder.addFormDataPart(fieldData.fieldName, fieldData.filename, fieldData.partBody);
319
-            }
320
-            return formBuilder.build();
312
+            return RequestBody.create(this.contentType, body);
321
         }
313
         }
322
         return null;
314
         return null;
315
+
323
     }
316
     }
324
 
317
 
325
     /**
318
     /**
337
             if (body.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
330
             if (body.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
338
                 String orgPath = body.substring(RNFetchBlobConst.FILE_PREFIX.length());
331
                 String orgPath = body.substring(RNFetchBlobConst.FILE_PREFIX.length());
339
                 orgPath = RNFetchBlobFS.normalizePath(orgPath);
332
                 orgPath = RNFetchBlobFS.normalizePath(orgPath);
340
-                // handle
333
+                // upload file from assets
341
                 if (RNFetchBlobFS.isAsset(orgPath)) {
334
                 if (RNFetchBlobFS.isAsset(orgPath)) {
342
                     try {
335
                     try {
343
                         String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
336
                         String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
337
+                        contentLength = RNFetchBlob.RCTContext.getAssets().openFd(assetName).getLength();
344
                         return RNFetchBlob.RCTContext.getAssets().open(assetName);
338
                         return RNFetchBlob.RCTContext.getAssets().open(assetName);
345
                     } catch (IOException e) {
339
                     } catch (IOException e) {
346
 //                        e.printStackTrace();
340
 //                        e.printStackTrace();
348
                 } else {
342
                 } else {
349
                     File f = new File(RNFetchBlobFS.normalizePath(orgPath));
343
                     File f = new File(RNFetchBlobFS.normalizePath(orgPath));
350
                     try {
344
                     try {
345
+                        if(!f.exists())
346
+                            f.createNewFile();
347
+                        contentLength = f.length();
351
                         return new FileInputStream(f);
348
                         return new FileInputStream(f);
352
-                    } catch (FileNotFoundException e) {
349
+                    } catch (Exception e) {
353
                         callback.invoke(e.getLocalizedMessage(), null);
350
                         callback.invoke(e.getLocalizedMessage(), null);
354
                     }
351
                     }
355
                 }
352
                 }
356
             } else {
353
             } else {
357
-                return new ByteArrayInputStream(Base64.decode(body, 0));
354
+                byte[] bytes = Base64.decode(body, 0);
355
+                contentLength = bytes.length;
356
+                return new ByteArrayInputStream(bytes);
358
             }
357
             }
359
         }
358
         }
360
         return null;
359
         return null;

+ 2
- 3
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobUtils.java View File

39
 
39
 
40
     }
40
     }
41
 
41
 
42
-    public static OkHttpClient getUnsafeOkHttpClient() {
42
+    public static OkHttpClient.Builder getUnsafeOkHttpClient() {
43
         try {
43
         try {
44
             // Create a trust manager that does not validate certificate chains
44
             // Create a trust manager that does not validate certificate chains
45
             final TrustManager[] trustAllCerts = new TrustManager[]{
45
             final TrustManager[] trustAllCerts = new TrustManager[]{
74
                 }
74
                 }
75
             });
75
             });
76
 
76
 
77
-            OkHttpClient okHttpClient = builder.build();
78
-            return okHttpClient;
77
+            return builder;
79
         } catch (Exception e) {
78
         } catch (Exception e) {
80
             throw new RuntimeException(e);
79
             throw new RuntimeException(e);
81
         }
80
         }

+ 0
- 71
src/android/src/main/java/com/RNFetchBlob/Request/FormPartBody.java View File

1
-package com.RNFetchBlob.Request;
2
-
3
-import com.RNFetchBlob.RNFetchBlobConst;
4
-import com.RNFetchBlob.RNFetchBlobFS;
5
-import com.facebook.react.bridge.ReactApplicationContext;
6
-import com.facebook.react.bridge.ReadableMap;
7
-import com.loopj.android.http.Base64;
8
-
9
-import java.io.File;
10
-import java.io.IOException;
11
-import java.io.InputStream;
12
-
13
-import okhttp3.MediaType;
14
-import okhttp3.RequestBody;
15
-
16
-/**
17
- * Created by wkh237 on 2016/7/12.
18
- */
19
-public class FormPartBody {
20
-
21
-    public String fieldName;
22
-    public String filename;
23
-    public RequestBody partBody;
24
-    public String stringBody;
25
-
26
-    public FormPartBody(ReactApplicationContext ctx, ReadableMap field) {
27
-        String data = field.getString("data");
28
-        String name = field.getString("name");
29
-        RequestBody partBody;
30
-        if (field.hasKey("filename")) {
31
-            MediaType mime = field.hasKey("type") ?
32
-                    MediaType.parse(field.getString("type")) : RNFetchBlobConst.MIME_OCTET;
33
-            String filename = field.getString("filename");
34
-            // upload from storage
35
-            if (data.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
36
-                String orgPath = data.substring(RNFetchBlobConst.FILE_PREFIX.length());
37
-                orgPath = RNFetchBlobFS.normalizePath(orgPath);
38
-                // path starts with content://
39
-                if (RNFetchBlobFS.isAsset(orgPath)) {
40
-                    try {
41
-                        String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
42
-                        InputStream in = ctx.getAssets().open(assetName);
43
-                        long length = ctx.getAssets().openFd(assetName).getLength();
44
-                        byte[] bytes = new byte[(int) length];
45
-                        in.read(bytes, 0, (int) length);
46
-                        in.close();
47
-                        partBody = RequestBody.create(mime, bytes, 0, (int) length);
48
-                    } catch (IOException e) {
49
-                        partBody = null;
50
-                    }
51
-                } else {
52
-                    File file = new File(RNFetchBlobFS.normalizePath(orgPath));
53
-                    partBody = RequestBody.create(mime, file);
54
-                }
55
-            }
56
-            // base64 embedded file content
57
-            else {
58
-                byte[] bytes = Base64.decode(data, 0);
59
-                partBody = RequestBody.create(mime, bytes, 0, bytes.length);
60
-            }
61
-            this.filename = filename;
62
-            this.fieldName = name;
63
-            this.partBody = partBody;
64
-        }
65
-        // data field
66
-        else {
67
-            this.fieldName = name;
68
-            this.stringBody = field.getString("data");
69
-        }
70
-    }
71
-}

+ 38
- 26
src/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java View File

10
 import java.io.FileOutputStream;
10
 import java.io.FileOutputStream;
11
 import java.io.IOException;
11
 import java.io.IOException;
12
 
12
 
13
+import okhttp3.MediaType;
13
 import okhttp3.ResponseBody;
14
 import okhttp3.ResponseBody;
14
 import okio.Buffer;
15
 import okio.Buffer;
15
 import okio.BufferedSource;
16
 import okio.BufferedSource;
20
 /**
21
 /**
21
  * Created by wkh237 on 2016/7/11.
22
  * Created by wkh237 on 2016/7/11.
22
  */
23
  */
23
-public class RNFetchBlobFileResp extends RNFetchBlobDefaultResp {
24
+public class RNFetchBlobFileResp extends ResponseBody {
24
 
25
 
26
+    String mTaskId;
27
+    ResponseBody originalBody;
25
     String mPath;
28
     String mPath;
29
+    long bytesUploaded = 0;
26
     ReactApplicationContext rctContext;
30
     ReactApplicationContext rctContext;
27
     FileOutputStream ofStream;
31
     FileOutputStream ofStream;
28
 
32
 
29
     public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path) throws IOException {
33
     public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path) throws IOException {
30
-        super(ctx, taskId, body);
34
+        super();
31
         this.rctContext = ctx;
35
         this.rctContext = ctx;
32
         this.mTaskId = taskId;
36
         this.mTaskId = taskId;
33
         this.originalBody = body;
37
         this.originalBody = body;
38
+        assert path != null;
34
         this.mPath = path;
39
         this.mPath = path;
35
-        File f = new File(path);
36
-        if(f.exists() == false)
37
-            f.createNewFile();
38
-        ofStream = new FileOutputStream(new File(path));
40
+        if (path != null) {
41
+            File f = new File(path);
42
+            if(f.exists() == false)
43
+                f.createNewFile();
44
+            ofStream = new FileOutputStream(new File(path));
45
+        }
39
     }
46
     }
40
 
47
 
48
+    @Override
49
+    public MediaType contentType() {
50
+        return originalBody.contentType();
51
+    }
52
+
53
+    @Override
54
+    public long contentLength() {
55
+        return originalBody.contentLength();
56
+    }
41
 
57
 
42
     @Override
58
     @Override
43
     public BufferedSource source() {
59
     public BufferedSource source() {
44
-        ProgressReportingSource source = new ProgressReportingSource(originalBody.source());
45
-        return Okio.buffer(source);
60
+        ProgressReportingSource countable = new ProgressReportingSource();
61
+        return Okio.buffer(countable);
46
     }
62
     }
47
 
63
 
48
     private class ProgressReportingSource implements Source {
64
     private class ProgressReportingSource implements Source {
49
-
50
-        BufferedSource mOriginalSource;
51
-        long bytesRead = 0;
52
-
53
-        ProgressReportingSource(BufferedSource originalSource) {
54
-            mOriginalSource = originalSource;
55
-        }
56
-
65
+        int count = 0;
57
         @Override
66
         @Override
58
         public long read(Buffer sink, long byteCount) throws IOException {
67
         public long read(Buffer sink, long byteCount) throws IOException {
59
-            bytesRead += byteCount;
60
-            byte [] bytes = new byte[10240];
61
-            long read = mOriginalSource.read(bytes);
62
-            ofStream.write(bytes);
63
-            WritableMap args = Arguments.createMap();
64
-            args.putString("taskId", mTaskId);
65
-            args.putString("written", String.valueOf(bytesRead));
66
-            args.putString("total", String.valueOf(contentLength()));
67
-            rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
68
-                    .emit("RNFetchBlobProgress", args);
68
+            count++;
69
+            byte [] bytes = new byte[(int) byteCount];
70
+            long read = originalBody.byteStream().read(bytes, 0, (int) byteCount);
71
+            if(read > 0) {
72
+                bytesUploaded += read;
73
+                ofStream.write(bytes, 0, (int) read);
74
+                WritableMap args = Arguments.createMap();
75
+                args.putString("taskId", mTaskId);
76
+                args.putString("written", String.valueOf(bytesUploaded));
77
+                args.putString("total", String.valueOf(contentLength()));
78
+                rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
79
+                        .emit("RNFetchBlobProgress", args);
80
+            }
69
             return read;
81
             return read;
70
         }
82
         }
71
 
83
 

+ 3
- 2
src/index.js View File

121
       }
121
       }
122
     })
122
     })
123
 
123
 
124
-    let subscription = emitter.addListener('RNFetchBlobProgress-upload', (e) => {
125
-      if(e.taskId === taskId && promise.onProgress) {
124
+    let subscriptionUpload = emitter.addListener('RNFetchBlobProgress-upload', (e) => {
125
+      if(e.taskId === taskId && promise.onUploadProgress) {
126
         promise.onUploadProgress(e.written, e.total)
126
         promise.onUploadProgress(e.written, e.total)
127
       }
127
       }
128
     })
128
     })
132
 
132
 
133
       // task done, remove event listener
133
       // task done, remove event listener
134
       subscription.remove()
134
       subscription.remove()
135
+      subscriptionUpload.remove()
135
       if(err)
136
       if(err)
136
         reject(new Error(err, data))
137
         reject(new Error(err, data))
137
       else {
138
       else {

+ 1
- 0
test-server/.gitignore View File

4
 !public/github2.jpg
4
 !public/github2.jpg
5
 !public/22mb-dummy
5
 !public/22mb-dummy
6
 !public/1mb-dummy
6
 !public/1mb-dummy
7
+!public/chunk-dummy
7
 !public/beethoven.mp3
8
 !public/beethoven.mp3
8
 !public/cat-fu.mp4
9
 !public/cat-fu.mp4
9
 !uploads/readme
10
 !uploads/readme

+ 0
- 0
test-server/dummy-res View File


BIN
test-server/dummy-res.png View File


+ 1
- 0
test-server/public/chunk-dummy View File

1
+12345678910abcdefg

+ 1
- 2
test-server/server.js View File

40
     console.log('test server running at port ',8123)
40
     console.log('test server running at port ',8123)
41
 })
41
 })
42
 
42
 
43
-var count = 0
44
 
43
 
45
 app.use(function(req,res,next){
44
 app.use(function(req,res,next){
46
-  console.log(chalk.green('request url=') + chalk.magenta(req.url), ++count)
45
+  console.log(chalk.green('request url=') + chalk.magenta(req.url))
47
   next()
46
   next()
48
 })
47
 })
49
 
48
 

+ 2
- 0
test/test-0.1.x-0.4.x.js View File

66
       { name : 'field2', data : 'hello2 !!'}
66
       { name : 'field2', data : 'hello2 !!'}
67
     ])
67
     ])
68
   .then((resp) => {
68
   .then((resp) => {
69
+    console.log(resp.json())
69
     resp = resp.json()
70
     resp = resp.json()
71
+
70
     report(
72
     report(
71
       <Assert key="check posted form data #1" expect="hello !!" actual={resp.fields.field1}/>,
73
       <Assert key="check posted form data #1" expect="hello !!" actual={resp.fields.field1}/>,
72
       <Assert key="check posted form data #2" expect="hello2 !!" actual={resp.fields.field2}/>,
74
       <Assert key="check posted form data #2" expect="hello2 !!" actual={resp.fields.field2}/>,

+ 0
- 62
test/test-0.5.1.js View File

185
     })
185
     })
186
 })
186
 })
187
 
187
 
188
-RNTest.config({
189
-  group : '0.5.1',
190
-  run : true,
191
-  expand : false,
192
-  timeout : 600000,
193
-})('Upload and download large file', (report, done) => {
194
-  let filename = '22mb-dummy-' + Date.now()
195
-  let begin = -1
196
-  let begin2 = -1
197
-  let deb = Date.now()
198
-  RNFetchBlob.config({
199
-    fileCache : true
200
-  })
201
-  .fetch('GET', `${TEST_SERVER_URL}/public/22mb-dummy`)
202
-  .progress((now, total) => {
203
-    if(begin === -1)
204
-      begin = Date.now()
205
-    if(Date.now() - deb < 1000)
206
-      return
207
-    deb = Date.now()
208
-    report(<Info uid="200" key="progress">
209
-      <Text>
210
-        {`download ${now} / ${total} bytes (${Math.floor(now / (Date.now() - begin))} kb/s)`}
211
-      </Text>
212
-    </Info>)
213
-  })
214
-  .then((res) => {
215
-    try {
216
-    deb = Date.now()
217
-    let promise =  RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
218
-      Authorization : `Bearer ${DROPBOX_TOKEN}`,
219
-      'Dropbox-API-Arg': '{\"path\": \"/rn-upload/'+filename+'\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}',
220
-      'Content-Type' : 'application/octet-stream',
221
-    }, RNFetchBlob.wrap(res.path()))
222
-    if(Platform.OS === 'ios') {
223
-      promise.progress((now, total) => {
224
-        if(Date.now() - deb < 1000)
225
-          return
226
-        deb = Date.now()
227
-        if(begin2 === -1)
228
-          begin2 = Date.now()
229
-        let speed = Math.floor(now / (Date.now() - begin2))
230
-        report(<Info uid="100"  key="progress">
231
-          <Text>
232
-            {`upload ${now} / ${total} bytes (${speed} kb/s)`}
233
-            {` ${Math.floor((total-now)/speed/1000)} seconds left`}
234
-          </Text>
235
-        </Info>)
236
-      })
237
-    }
238
-    return promise
239
-  } catch(err) { console.log(err) }
240
-  })
241
-  .then((res) => {
242
-    report(<Assert
243
-      key="upload should success without crashing app"
244
-      expect={filename}
245
-      actual={res.json().name}/>)
246
-    done()
247
-  })
248
-})
249
-
250
 describe('Session create mechanism test', (report, done) => {
188
 describe('Session create mechanism test', (report, done) => {
251
   let sessionName = 'foo-' + Date.now()
189
   let sessionName = 'foo-' + Date.now()
252
   testSessionName = sessionName
190
   testSessionName = sessionName

+ 1
- 1
test/test-0.5.2.js View File

58
 describe('POST request with params', (report, done) => {
58
 describe('POST request with params', (report, done) => {
59
   let time = Date.now()
59
   let time = Date.now()
60
   RNFetchBlob.config({ fileCache : true })
60
   RNFetchBlob.config({ fileCache : true })
61
-    .fetch('POST', `${TEST_SERVER_URL}/params?time=${time}&name=RNFetchBlobParams&lang=中文`)
61
+    .fetch('POST', `${TEST_SERVER_URL}/params?time=${time}&name=RNFetchBlobParams&lang=中文`, {}, RNFetchBlob.base64.encode('123'))
62
     .then((resp) => {
62
     .then((resp) => {
63
       let file = resp.path()
63
       let file = resp.path()
64
       return RNFetchBlob.fs.readStream(resp.path(), 'utf8')
64
       return RNFetchBlob.fs.readStream(resp.path(), 'utf8')

+ 63
- 5
test/test-0.6.3.js View File

27
 
27
 
28
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
28
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
29
 
29
 
30
-describe('massive HTTP request', (report, done) => {
31
-  try {
30
+false && describe('massive HTTP request', (report, done) => {
31
+  return
32
   let promises = []
32
   let promises = []
33
   let progress = []
33
   let progress = []
34
   let begin = Date.now()
34
   let begin = Date.now()
61
     // Timer.clearInterval(it)
61
     // Timer.clearInterval(it)
62
     done()
62
     done()
63
   })
63
   })
64
-} catch(err) {
65
-  console.log(err)
66
-}
67
 
64
 
68
 })
65
 })
66
+
67
+RNTest.config({
68
+  group : '0.7.0',
69
+  run : true,
70
+  expand : false,
71
+  timeout : 600000,
72
+})('Upload and download large file', (report, done) => {
73
+  let filename = '22mb-dummy-' + Date.now()
74
+  let begin = -1
75
+  let begin2 = -1
76
+  let deb = Date.now()
77
+  RNFetchBlob.config({
78
+    fileCache : true
79
+  })
80
+  .fetch('GET', `${TEST_SERVER_URL}/public/22mb-dummy`)
81
+  .progress((now, total) => {
82
+    if(begin === -1)
83
+      begin = Date.now()
84
+    if(Date.now() - deb < 1000)
85
+      return
86
+    deb = Date.now()
87
+    report(<Info uid="200" key="progress">
88
+      <Text>
89
+        {`download ${now} / ${total} bytes (${Math.floor(now / (Date.now() - begin))} kb/s)`}
90
+      </Text>
91
+    </Info>)
92
+  })
93
+  .then((res) => {
94
+    try {
95
+    deb = Date.now()
96
+    // let promise =  RNFetchBlob.fetch('POST', `${TEST_SERVER_URL}/raw`, {
97
+    let promise =  RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
98
+      Authorization : `Bearer ${DROPBOX_TOKEN}`,
99
+      'Dropbox-API-Arg': '{\"path\": \"/rn-upload/'+filename+'\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}',
100
+      'Content-Type' : 'application/octet-stream',
101
+    }, RNFetchBlob.wrap(res.path()))
102
+    promise.uploadProgress((now, total) => {
103
+      if(Date.now() - deb < 1000)
104
+        return
105
+      deb = Date.now()
106
+      if(begin2 === -1)
107
+        begin2 = Date.now()
108
+      let speed = Math.floor(now / (Date.now() - begin2))
109
+      report(<Info uid="100"  key="progress">
110
+        <Text>
111
+          {`upload ${now} / ${total} bytes (${speed} kb/s)`}
112
+          {` ${Math.floor((total-now)/speed/1000)} seconds left`}
113
+        </Text>
114
+      </Info>)
115
+    })
116
+    return promise
117
+  } catch(err) { console.log(err) }
118
+  })
119
+  .then((res) => {
120
+    report(<Assert
121
+      key="upload should success without crashing app"
122
+      expect={filename}
123
+      actual={res.json().name}/>)
124
+    done()
125
+  })
126
+})

+ 15
- 9
test/test-init.js View File

13
   Image,
13
   Image,
14
 } from 'react-native';
14
 } from 'react-native';
15
 
15
 
16
-const { Assert, Comparer, Info, describe, prop } = RNTest
16
+const { Assert, Comparer, Info, prop } = RNTest
17
 
17
 
18
 // test environment variables
18
 // test environment variables
19
 
19
 
25
   image : {
25
   image : {
26
     width: Dimensions.get('window').width*0.9,
26
     width: Dimensions.get('window').width*0.9,
27
     height : Dimensions.get('window').width*0.9,
27
     height : Dimensions.get('window').width*0.9,
28
-    margin :16
28
+    margin : 16
29
   }
29
   }
30
 })
30
 })
31
 
31
 
32
 const { TEST_SERVER_URL, FILENAME, DROPBOX_TOKEN, styles, image } = prop()
32
 const { TEST_SERVER_URL, FILENAME, DROPBOX_TOKEN, styles, image } = prop()
33
 
33
 
34
+const describe = RNTest.config({
35
+  run : true,
36
+  expand : false,
37
+  timeout : 5000,
38
+})
39
+
34
 // init
40
 // init
35
 
41
 
36
 describe('GET image from server', (report, done) => {
42
 describe('GET image from server', (report, done) => {
53
 
59
 
54
 
60
 
55
 require('./test-0.1.x-0.4.x')
61
 require('./test-0.1.x-0.4.x')
56
-require('./test-0.5.1')
57
-require('./test-0.5.2')
58
-require('./test-0.6.0')
59
-require('./test-0.6.2')
60
-require('./test-0.6.3')
61
-require('./test-fs')
62
-require('./test-android')
62
+// require('./test-0.5.1')
63
+// require('./test-0.5.2')
64
+// require('./test-0.6.0')
65
+// require('./test-0.6.2')
66
+// require('./test-0.6.3')
67
+// require('./test-fs')
68
+// require('./test-android')