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

Commit 0fb6635

Browse files
committed
Fix Android upload progress #94
1 parent 140ce1b commit 0fb6635

File tree

1 file changed

+73
-96
lines changed

1 file changed

+73
-96
lines changed

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

+73-96
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.RNFetchBlob;
22

33
import android.util.Base64;
4-
import android.util.Log;
54

65
import com.facebook.react.bridge.Arguments;
76
import com.facebook.react.bridge.ReactApplicationContext;
@@ -13,23 +12,14 @@
1312
import java.io.ByteArrayInputStream;
1413
import java.io.File;
1514
import java.io.FileInputStream;
16-
import java.io.FileNotFoundException;
1715
import java.io.FileOutputStream;
1816
import java.io.IOException;
1917
import java.io.InputStream;
20-
import java.nio.ByteBuffer;
21-
import java.nio.MappedByteBuffer;
2218
import java.util.ArrayList;
23-
import java.util.HashMap;
2419

2520
import okhttp3.MediaType;
2621
import okhttp3.RequestBody;
27-
import okhttp3.FormBody;
28-
import okio.Buffer;
2922
import okio.BufferedSink;
30-
import okio.ForwardingSink;
31-
import okio.Okio;
32-
import okio.Sink;
3323

3424
/**
3525
* Created by wkh237 on 2016/7/11.
@@ -38,7 +28,6 @@ public class RNFetchBlobBody extends RequestBody{
3828

3929
InputStream requestStream;
4030
long contentLength = 0;
41-
long bytesWritten = 0;
4231
ReadableArray form;
4332
String mTaskId;
4433
String rawBody;
@@ -47,59 +36,84 @@ public class RNFetchBlobBody extends RequestBody{
4736
File bodyCache;
4837

4938

39+
/**
40+
* Single file or raw content request constructor
41+
* @param taskId
42+
* @param type
43+
* @param form
44+
* @param contentType
45+
*/
5046
public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, ReadableArray form, MediaType contentType) {
5147
this.mTaskId = taskId;
5248
this.form = form;
5349
requestType = type;
5450
mime = contentType;
5551
try {
5652
bodyCache = createMultipartBodyCache();
53+
requestStream = new FileInputStream(bodyCache);
5754
contentLength = bodyCache.length();
58-
} catch (IOException e) {
59-
e.printStackTrace();
55+
} catch(Exception ex) {
56+
ex.printStackTrace();
57+
RNFetchBlobUtils.emitWarningEvent("RNFetchBlob failed to create request multipart body :" + ex.getLocalizedMessage());
6058
}
6159
}
6260

61+
/**
62+
* Multipart request constructor
63+
* @param taskId
64+
* @param type
65+
* @param rawBody
66+
* @param contentType
67+
*/
6368
public RNFetchBlobBody(String taskId, RNFetchBlobReq.RequestType type, String rawBody, MediaType contentType) {
6469
this.mTaskId = taskId;
6570
requestType = type;
6671
this.rawBody = rawBody;
6772
mime = contentType;
68-
if(rawBody != null) {
69-
if(requestType == RNFetchBlobReq.RequestType.AsIs)
70-
contentLength = rawBody.length();
71-
else
72-
contentLength = caculateOctetContentLength();
73+
if(rawBody == null) {
74+
this.rawBody = "";
75+
requestType = RNFetchBlobReq.RequestType.AsIs;
76+
}
77+
try {
78+
switch (requestType) {
79+
case SingleFile:
80+
requestStream = getReuqestStream();
81+
contentLength = requestStream.available();
82+
break;
83+
case AsIs:
84+
contentLength = this.rawBody.getBytes().length;
85+
break;
86+
case Others:
87+
break;
88+
}
89+
} catch(Exception ex) {
90+
ex.printStackTrace();
91+
RNFetchBlobUtils.emitWarningEvent("RNFetchBlob failed to create single content request body :" + ex.getLocalizedMessage() + "\r\n");
7392
}
93+
7494
}
7595

7696
@Override
7797
public long contentLength() {
7898
return contentLength;
7999
}
100+
80101
@Override
81102
public MediaType contentType() {
82103
return mime;
83104
}
84105

85106
@Override
86-
public void writeTo(BufferedSink sink) throws IOException {
87-
88-
ProgressReportingSource source = new ProgressReportingSource(sink, mTaskId);
89-
BufferedSink buffer = Okio.buffer(source);
90-
switch (requestType) {
91-
case Form:
92-
pipeStreamToSink(new FileInputStream(bodyCache), sink);
93-
break;
94-
case SingleFile:
95-
if(requestStream != null)
96-
pipeStreamToSink(requestStream, sink);
97-
break;
98-
case AsIs:
99-
writeRawData(sink);
100-
break;
107+
public void writeTo(BufferedSink sink) {
108+
try {
109+
if (requestType == RNFetchBlobReq.RequestType.AsIs)
110+
sink.write(rawBody.getBytes());
111+
else
112+
pipeStreamToSink(requestStream, sink);
113+
} catch(Exception ex) {
114+
RNFetchBlobUtils.emitWarningEvent(ex.getLocalizedMessage());
115+
ex.printStackTrace();
101116
}
102-
buffer.flush();
103117
}
104118

105119
boolean clearRequestBody() {
@@ -114,8 +128,8 @@ boolean clearRequestBody() {
114128
return true;
115129
}
116130

117-
private long caculateOctetContentLength() {
118-
long total = 0;
131+
private InputStream getReuqestStream() throws Exception {
132+
119133
// upload from storage
120134
if (rawBody.startsWith(RNFetchBlobConst.FILE_PREFIX)) {
121135
String orgPath = rawBody.substring(RNFetchBlobConst.FILE_PREFIX.length());
@@ -124,32 +138,30 @@ private long caculateOctetContentLength() {
124138
if (RNFetchBlobFS.isAsset(orgPath)) {
125139
try {
126140
String assetName = orgPath.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "");
127-
total += RNFetchBlob.RCTContext.getAssets().openFd(assetName).getLength();
128-
requestStream = RNFetchBlob.RCTContext.getAssets().open(assetName);
129-
} catch (IOException e) {
130-
RNFetchBlobUtils.emitWarningEvent(e.getLocalizedMessage());
141+
return RNFetchBlob.RCTContext.getAssets().open(assetName);
142+
} catch (Exception e) {
143+
throw new Exception("error when getting request stream from asset : " +e.getLocalizedMessage());
131144
}
132145
} else {
133146
File f = new File(RNFetchBlobFS.normalizePath(orgPath));
134147
try {
135148
if(!f.exists())
136149
f.createNewFile();
137-
total += f.length();
138-
requestStream = new FileInputStream(f);
150+
return new FileInputStream(f);
139151
} catch (Exception e) {
140-
RNFetchBlobUtils.emitWarningEvent("RNetchBlob error when counting content length: " +e.getLocalizedMessage());
152+
throw new Exception("error when getting request stream: " +e.getLocalizedMessage());
141153
}
142154
}
143-
} else {
155+
}
156+
// base 64 encoded
157+
else {
144158
try {
145159
byte[] bytes = Base64.decode(rawBody, 0);
146-
requestStream = new ByteArrayInputStream(bytes);
147-
total += requestStream.available();
160+
return new ByteArrayInputStream(bytes);
148161
} catch(Exception ex) {
149-
RNFetchBlobUtils.emitWarningEvent("RNetchBlob error when counting content length: " +ex.getLocalizedMessage());
162+
throw new Exception("error when getting request stream: " + ex.getLocalizedMessage());
150163
}
151164
}
152-
return total;
153165
}
154166

155167
/**
@@ -192,7 +204,7 @@ private File createMultipartBodyCache() throws IOException {
192204
InputStream in = ctx.getAssets().open(assetName);
193205
pipeStreamToFileStream(in, os);
194206
} catch (IOException e) {
195-
RNFetchBlobUtils.emitWarningEvent("RNFetchBlob Failed to create form data asset :" + orgPath + ", " + e.getLocalizedMessage() );
207+
RNFetchBlobUtils.emitWarningEvent("Failed to create form data asset :" + orgPath + ", " + e.getLocalizedMessage() );
196208
}
197209
}
198210
// data from normal files
@@ -203,16 +215,14 @@ private File createMultipartBodyCache() throws IOException {
203215
pipeStreamToFileStream(fs, os);
204216
}
205217
else {
206-
RNFetchBlobUtils.emitWarningEvent("RNFetchBlob Failed to create form data from path :" + orgPath + ", file not exists.");
218+
RNFetchBlobUtils.emitWarningEvent("Failed to create form data from path :" + orgPath + ", file not exists.");
207219
}
208220
}
209221
}
210222
// base64 embedded file content
211223
else {
212224
byte[] b = Base64.decode(data, 0);
213225
os.write(b);
214-
bytesWritten += b.length;
215-
emitUploadProgress();
216226
}
217227

218228
}
@@ -222,7 +232,6 @@ private File createMultipartBodyCache() throws IOException {
222232
header += "Content-Type: " + field.mime + "\r\n\r\n";
223233
os.write(header.getBytes());
224234
byte[] fieldData = field.data.getBytes();
225-
bytesWritten += fieldData.length;
226235
os.write(fieldData);
227236
}
228237
// form end
@@ -236,28 +245,22 @@ private File createMultipartBodyCache() throws IOException {
236245
return outputFile;
237246
}
238247

239-
/**
240-
* Write data to request body as-is
241-
* @param sink
242-
*/
243-
private void writeRawData(BufferedSink sink) throws IOException {
244-
byte[] bytes = rawBody.getBytes();
245-
contentLength = bytes.length;
246-
sink.write(bytes);
247-
}
248-
249248
/**
250249
* Pipe input stream to request body output stream
251250
* @param stream The input stream
252251
* @param sink The request body buffer sink
253252
* @throws IOException
254253
*/
255-
private void pipeStreamToSink(InputStream stream, BufferedSink sink) throws IOException {
254+
private void pipeStreamToSink(InputStream stream, BufferedSink sink) throws Exception {
255+
256256
byte [] chunk = new byte[10240];
257+
int totalWritten = 0;
257258
int read;
258259
while((read = stream.read(chunk, 0, 10240)) > 0) {
259260
if(read > 0) {
260261
sink.write(chunk, 0, read);
262+
totalWritten += read;
263+
emitUploadProgress(totalWritten);
261264
}
262265
}
263266
stream.close();
@@ -356,45 +359,19 @@ public FormField(ReadableMap rawData) {
356359
}
357360
}
358361

359-
private void emitUploadProgress() {
362+
/**
363+
* Emit progress event
364+
* @param written
365+
*/
366+
private void emitUploadProgress(int written) {
360367
WritableMap args = Arguments.createMap();
361368
args.putString("taskId", mTaskId);
362-
args.putString("written", String.valueOf(bytesWritten));
369+
args.putString("written", String.valueOf(written));
363370
args.putString("total", String.valueOf(contentLength));
364371

365372
// emit event to js context
366373
RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
367374
.emit(RNFetchBlobConst.EVENT_UPLOAD_PROGRESS, args);
368375
}
369376

370-
private final class ProgressReportingSource extends ForwardingSink {
371-
372-
private long bytesWritten = 0;
373-
private String mTaskId;
374-
private Sink delegate;
375-
376-
public ProgressReportingSource (Sink delegate, String taskId) {
377-
super(delegate);
378-
this.mTaskId = taskId;
379-
this.delegate = delegate;
380-
}
381-
382-
@Override
383-
public void write(Buffer source, long byteCount) throws IOException {
384-
delegate.write(source, byteCount);
385-
// on progress, emit RNFetchBlobProgress upload progress event with ticketId,
386-
// bytesWritten, and totalSize
387-
bytesWritten += byteCount;
388-
WritableMap args = Arguments.createMap();
389-
args.putString("taskId", mTaskId);
390-
args.putString("written", String.valueOf(bytesWritten));
391-
args.putString("total", String.valueOf(contentLength));
392-
393-
if(RNFetchBlobReq.isReportUploadProgress(mTaskId)) {
394-
// emit event to js context
395-
RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
396-
.emit(RNFetchBlobConst.EVENT_UPLOAD_PROGRESS, args);
397-
}
398-
}
399-
}
400377
}

0 commit comments

Comments
 (0)