Skip to content
This repository was archived by the owner on Mar 16, 2019. It is now read-only.

Commit 1538401

Browse files
committed
0.7.0 Android code refactor
1 parent c00f557 commit 1538401

File tree

5 files changed

+163
-208
lines changed

5 files changed

+163
-208
lines changed

src/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,13 @@ public void readStream(String path, String encoding, int bufferSize) {
151151
}
152152

153153
@ReactMethod
154-
public void cancel(String taskId) {
155-
RNFetchBlobReq.cancelTask(taskId);
154+
public void cancelRequest(String taskId, Callback callback) {
155+
try {
156+
RNFetchBlobReq.cancelTask(taskId);
157+
callback.invoke(null, taskId);
158+
} catch (Exception ex) {
159+
callback.invoke(ex.getLocalizedMessage(), null);
160+
}
156161
}
157162

158163
@ReactMethod

src/android/src/main/java/com/RNFetchBlob/RNFetchBlobBody.java

Lines changed: 150 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
package com.RNFetchBlob;
22

3-
import android.net.Uri;
43
import android.util.Base64;
54
import android.util.Log;
65

76
import com.facebook.react.bridge.Arguments;
87
import com.facebook.react.bridge.ReactApplicationContext;
98
import com.facebook.react.bridge.ReadableArray;
109
import com.facebook.react.bridge.ReadableMap;
11-
import com.facebook.react.bridge.WritableArray;
1210
import com.facebook.react.bridge.WritableMap;
1311
import com.facebook.react.modules.core.DeviceEventManagerModule;
1412

13+
import java.io.ByteArrayInputStream;
1514
import java.io.File;
1615
import java.io.FileInputStream;
17-
import java.io.FileNotFoundException;
1816
import java.io.IOException;
1917
import java.io.InputStream;
2018
import java.util.ArrayList;
@@ -24,7 +22,6 @@
2422
import okhttp3.RequestBody;
2523
import okio.Buffer;
2624
import okio.BufferedSink;
27-
import okio.ByteString;
2825
import okio.ForwardingSink;
2926
import okio.Okio;
3027
import okio.Sink;
@@ -39,18 +36,24 @@ public class RNFetchBlobBody extends RequestBody{
3936
long bytesWritten = 0;
4037
ReadableArray form;
4138
String mTaskId;
39+
String rawBody;
4240
RNFetchBlobReq.RequestType requestType;
4341
MediaType mime;
4442

45-
public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, ReadableArray form, InputStream stream, long size, MediaType contentType) {
43+
public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, ReadableArray form, MediaType contentType) {
4644
this.mTaskId = taskId;
4745
this.form = form;
48-
requestStream = stream;
49-
contentLength = size;
5046
requestType = type;
5147
mime = contentType;
5248
}
5349

50+
public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, String rawBody, MediaType contentType) {
51+
this.mTaskId = taskId;
52+
requestType = type;
53+
this.rawBody = rawBody;
54+
mime = contentType;
55+
}
56+
5457
@Override
5558
public MediaType contentType() {
5659
return mime;
@@ -59,85 +62,134 @@ public MediaType contentType() {
5962
@Override
6063
public void writeTo(BufferedSink sink) throws IOException {
6164

62-
ProgressReportingSource source = new ProgressReportingSource(sink, mTaskId, contentLength());
65+
ProgressReportingSource source = new ProgressReportingSource(sink, mTaskId);
6366
BufferedSink buffer = Okio.buffer(source);
6467
switch (requestType) {
6568
case Form:
66-
String boundary = "RNFetchBlob-" + mTaskId;
67-
ArrayList<FormField> fields = countFormDataLength();
68-
ReactApplicationContext ctx = RNFetchBlob.RCTContext;
69-
for(int i = 0;i < fields.size(); i++) {
70-
FormField field = fields.get(i);
71-
String data = field.data;
72-
String name = field.name;
73-
// skip invalid fields
74-
if(name == null || data == null)
75-
continue;
76-
// form begin
77-
String header = "--" + boundary + "\r\n";
78-
if (field.filename != null) {
79-
header += "Content-Disposition: form-data; name=" + name + "; filename=" + field.filename + "\r\n";
80-
header += "Content-Type: " + field.mime+ "\r\n\r\n";
81-
sink.write(header.getBytes());
82-
// file field header end
83-
// upload from storage
84-
if (data.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
85-
String orgPath = data.substring(RNFetchBlobConst.FILE_PREFIX.length());
86-
orgPath = RNFetchBlobFS.normalizePath(orgPath);
87-
// path starts with content://
88-
if (RNFetchBlobFS.isAsset(orgPath)) {
89-
try {
90-
String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
91-
InputStream in = ctx.getAssets().open(assetName);
92-
pipeStreamToSink(in, sink);
93-
} catch (IOException e) {
94-
Log.e("RNFetchBlob", "Failed to create form data asset :" + orgPath + ", " + e.getLocalizedMessage() );
95-
}
96-
}
97-
// data from normal files
98-
else {
99-
File file = new File(RNFetchBlobFS.normalizePath(orgPath));
100-
if(file.exists()) {
101-
FileInputStream fs = new FileInputStream(file);
102-
pipeStreamToSink(fs, sink);
103-
}
104-
else {
105-
Log.e("RNFetchBlob", "Failed to create form data from path :" + orgPath + "file not exists.");
106-
}
107-
}
108-
}
109-
// base64 embedded file content
110-
else {
111-
byte[] b = Base64.decode(data, 0);
112-
sink.write(b);
113-
bytesWritten += b.length;
114-
emitUploadProgress(bytesWritten, contentLength);
115-
}
69+
writeFormData(sink);
70+
break;
71+
case SingleFile:
72+
writeOctetData(sink);
73+
break;
74+
}
75+
buffer.flush();
76+
}
11677

78+
private void writeFormData(BufferedSink sink) throws IOException {
79+
String boundary = "RNFetchBlob-" + mTaskId;
80+
ArrayList<FormField> fields = countFormDataLength();
81+
ReactApplicationContext ctx = RNFetchBlob.RCTContext;
82+
for(int i = 0;i < fields.size(); i++) {
83+
FormField field = fields.get(i);
84+
String data = field.data;
85+
String name = field.name;
86+
// skip invalid fields
87+
if(name == null || data == null)
88+
continue;
89+
// form begin
90+
String header = "--" + boundary + "\r\n";
91+
if (field.filename != null) {
92+
header += "Content-Disposition: form-data; name=" + name + "; filename=" + field.filename + "\r\n";
93+
header += "Content-Type: " + field.mime+ "\r\n\r\n";
94+
sink.write(header.getBytes());
95+
// file field header end
96+
// upload from storage
97+
if (data.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
98+
String orgPath = data.substring(RNFetchBlobConst.FILE_PREFIX.length());
99+
orgPath = RNFetchBlobFS.normalizePath(orgPath);
100+
// path starts with content://
101+
if (RNFetchBlobFS.isAsset(orgPath)) {
102+
try {
103+
String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
104+
InputStream in = ctx.getAssets().open(assetName);
105+
pipeStreamToSink(in, sink);
106+
} catch (IOException e) {
107+
Log.e("RNFetchBlob", "Failed to create form data asset :" + orgPath + ", " + e.getLocalizedMessage() );
108+
}
117109
}
118-
// data field
110+
// data from normal files
119111
else {
120-
header += "Content-Disposition: form-data; name=" + name + "\r\n";
121-
header += "Content-Type: " + field.mime + "\r\n\r\n";
122-
sink.write(header.getBytes());
123-
byte[] fieldData = field.data.getBytes();
124-
bytesWritten += fieldData.length;
125-
sink.write(fieldData);
112+
File file = new File(RNFetchBlobFS.normalizePath(orgPath));
113+
if(file.exists()) {
114+
FileInputStream fs = new FileInputStream(file);
115+
pipeStreamToSink(fs, sink);
116+
}
117+
else {
118+
Log.e("RNFetchBlob", "Failed to create form data from path :" + orgPath + "file not exists.");
119+
}
126120
}
127-
// form end
128-
sink.write("\r\n".getBytes());
129121
}
130-
// close the form
131-
byte[] end = ("--" + boundary + "--\r\n").getBytes();
132-
sink.write(end);
133-
break;
134-
case SingleFile:
135-
pipeStreamToSink(requestStream, sink);
136-
break;
122+
// base64 embedded file content
123+
else {
124+
byte[] b = Base64.decode(data, 0);
125+
sink.write(b);
126+
bytesWritten += b.length;
127+
emitUploadProgress();
128+
}
129+
130+
}
131+
// data field
132+
else {
133+
header += "Content-Disposition: form-data; name=" + name + "\r\n";
134+
header += "Content-Type: " + field.mime + "\r\n\r\n";
135+
sink.write(header.getBytes());
136+
byte[] fieldData = field.data.getBytes();
137+
bytesWritten += fieldData.length;
138+
sink.write(fieldData);
139+
}
140+
// form end
141+
sink.write("\r\n".getBytes());
137142
}
138-
buffer.flush();
143+
// close the form
144+
byte[] end = ("--" + boundary + "--\r\n").getBytes();
145+
sink.write(end);
146+
}
147+
148+
/**
149+
* Write octet stream data to request body
150+
* @param sink
151+
*/
152+
private void writeOctetData(BufferedSink sink) throws IOException {
153+
// upload from storage
154+
if (rawBody.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
155+
String orgPath = rawBody.substring(RNFetchBlobConst.FILE_PREFIX.length());
156+
orgPath = RNFetchBlobFS.normalizePath(orgPath);
157+
// upload file from assets
158+
if (RNFetchBlobFS.isAsset(orgPath)) {
159+
try {
160+
String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
161+
contentLength = RNFetchBlob.RCTContext.getAssets().openFd(assetName).getLength();
162+
requestStream = RNFetchBlob.RCTContext.getAssets().open(assetName);
163+
} catch (IOException e) {
164+
// e.printStackTrace();
165+
}
166+
} else {
167+
File f = new File(RNFetchBlobFS.normalizePath(orgPath));
168+
try {
169+
if(!f.exists())
170+
f.createNewFile();
171+
contentLength = f.length();
172+
requestStream = new FileInputStream(f);
173+
} catch (Exception e) {
174+
// callback.invoke(e.getLocalizedMessage(), null);
175+
}
176+
}
177+
} else {
178+
byte[] bytes = Base64.decode(rawBody, 0);
179+
contentLength = bytes.length;
180+
requestStream = new ByteArrayInputStream(bytes);
181+
}
182+
if(requestStream != null)
183+
pipeStreamToSink(requestStream, sink);
184+
139185
}
140186

187+
/**
188+
* Pipe input stream to request body output stream
189+
* @param stream The input stream
190+
* @param sink The request body buffer sink
191+
* @throws IOException
192+
*/
141193
private void pipeStreamToSink(InputStream stream, BufferedSink sink) throws IOException {
142194
byte [] chunk = new byte[10240];
143195
int read = stream.read(chunk, 0, 10240);
@@ -150,28 +202,21 @@ private void pipeStreamToSink(InputStream stream, BufferedSink sink) throws IOEx
150202
if(read > 0) {
151203
sink.write(chunk, 0, read);
152204
bytesWritten += read;
153-
emitUploadProgress(bytesWritten, contentLength);
205+
emitUploadProgress();
154206
}
155207

156208
}
157209
stream.close();
158210
}
159211

160-
private void emitUploadProgress(long current, long total) {
161-
WritableMap args = Arguments.createMap();
162-
args.putString("taskId", mTaskId);
163-
args.putString("written", String.valueOf(bytesWritten));
164-
args.putString("total", String.valueOf(contentLength));
165-
166-
// emit event to js context
167-
RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
168-
.emit(RNFetchBlobConst.EVENT_UPLOAD_PROGRESS, args);
212+
private void writeBufferToSink(byte [] bytes, BufferedSink sink) throws IOException {
213+
bytesWritten += bytes.length;
214+
sink.write(bytes);
215+
emitUploadProgress();
169216
}
170217

171-
172-
173218
/**
174-
* Compute a proximate content length for form data
219+
* Compute approximate content length for form data
175220
* @return
176221
*/
177222
private ArrayList<FormField> countFormDataLength() {
@@ -218,6 +263,10 @@ private ArrayList<FormField> countFormDataLength() {
218263
return list;
219264
}
220265

266+
/**
267+
* Since ReadableMap could only be access once, we have to store the field into a map for
268+
* repeatedly access.
269+
*/
221270
private class FormField {
222271
public String name;
223272
public String filename;
@@ -239,17 +288,26 @@ public FormField(ReadableMap rawData) {
239288
}
240289
}
241290

291+
private void emitUploadProgress() {
292+
WritableMap args = Arguments.createMap();
293+
args.putString("taskId", mTaskId);
294+
args.putString("written", String.valueOf(bytesWritten));
295+
args.putString("total", String.valueOf(contentLength));
296+
297+
// emit event to js context
298+
RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
299+
.emit(RNFetchBlobConst.EVENT_UPLOAD_PROGRESS, args);
300+
}
301+
242302
private final class ProgressReportingSource extends ForwardingSink {
243303

244304
private long bytesWritten = 0;
245305
private String mTaskId;
246-
private long mContentLength ;
247306
private Sink delegate;
248307

249-
public ProgressReportingSource (Sink delegate, String taskId, long contentLength) {
308+
public ProgressReportingSource (Sink delegate, String taskId) {
250309
super(delegate);
251310
this.mTaskId = taskId;
252-
this.mContentLength = contentLength;
253311
this.delegate = delegate;
254312
}
255313

@@ -262,7 +320,7 @@ public void write(Buffer source, long byteCount) throws IOException {
262320
WritableMap args = Arguments.createMap();
263321
args.putString("taskId", mTaskId);
264322
args.putString("written", String.valueOf(bytesWritten));
265-
args.putString("total", String.valueOf(mContentLength ));
323+
args.putString("total", String.valueOf(contentLength));
266324

267325
// emit event to js context
268326
RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)

0 commit comments

Comments
 (0)