|
9 | 9 |
|
10 | 10 | package com.facebook.react.modules.network; |
11 | 11 |
|
| 12 | +import com.facebook.common.internal.CountingOutputStream; |
| 13 | + |
12 | 14 | import java.io.IOException; |
| 15 | + |
13 | 16 | import okhttp3.MediaType; |
14 | 17 | import okhttp3.RequestBody; |
15 | 18 | import okio.BufferedSink; |
16 | | -import okio.Buffer; |
17 | | -import okio.Sink; |
18 | | -import okio.ForwardingSink; |
19 | 19 | import okio.Okio; |
| 20 | +import okio.Sink; |
20 | 21 |
|
21 | 22 | public class ProgressRequestBody extends RequestBody { |
22 | 23 |
|
23 | 24 | private final RequestBody mRequestBody; |
24 | 25 | private final ProgressListener mProgressListener; |
25 | 26 | private BufferedSink mBufferedSink; |
| 27 | + private long mContentLength = 0L; |
26 | 28 |
|
27 | 29 | public ProgressRequestBody(RequestBody requestBody, ProgressListener progressListener) { |
28 | | - mRequestBody = requestBody; |
29 | | - mProgressListener = progressListener; |
| 30 | + mRequestBody = requestBody; |
| 31 | + mProgressListener = progressListener; |
30 | 32 | } |
31 | 33 |
|
32 | 34 | @Override |
33 | 35 | public MediaType contentType() { |
34 | | - return mRequestBody.contentType(); |
| 36 | + return mRequestBody.contentType(); |
35 | 37 | } |
36 | 38 |
|
37 | 39 | @Override |
38 | 40 | public long contentLength() throws IOException { |
39 | | - return mRequestBody.contentLength(); |
| 41 | + if (mContentLength == 0) { |
| 42 | + mContentLength = mRequestBody.contentLength(); |
| 43 | + } |
| 44 | + return mContentLength; |
40 | 45 | } |
41 | 46 |
|
42 | 47 | @Override |
43 | 48 | public void writeTo(BufferedSink sink) throws IOException { |
44 | | - if (mBufferedSink == null) { |
45 | | - mBufferedSink = Okio.buffer(sink(sink)); |
46 | | - } |
47 | | - mRequestBody.writeTo(mBufferedSink); |
48 | | - mBufferedSink.flush(); |
| 49 | + if (mBufferedSink == null) { |
| 50 | + mBufferedSink = Okio.buffer(outputStreamSink(sink)); |
| 51 | + } |
| 52 | + |
| 53 | + // contentLength changes for input streams, since we're using inputStream.available(), |
| 54 | + // so get the length before writing to the sink |
| 55 | + contentLength(); |
| 56 | + |
| 57 | + mRequestBody.writeTo(mBufferedSink); |
| 58 | + mBufferedSink.flush(); |
49 | 59 | } |
50 | 60 |
|
51 | | - private Sink sink(Sink sink) { |
52 | | - return new ForwardingSink(sink) { |
53 | | - long bytesWritten = 0L; |
54 | | - long contentLength = 0L; |
| 61 | + private Sink outputStreamSink(BufferedSink sink) { |
| 62 | + return Okio.sink(new CountingOutputStream(sink.outputStream()) { |
| 63 | + @Override |
| 64 | + public void write(byte[] data, int offset, int byteCount) throws IOException { |
| 65 | + super.write(data, offset, byteCount); |
| 66 | + sendProgressUpdate(); |
| 67 | + } |
55 | 68 |
|
56 | | - @Override |
57 | | - public void write(Buffer source, long byteCount) throws IOException { |
58 | | - super.write(source, byteCount); |
59 | | - if (contentLength == 0) { |
60 | | - contentLength = contentLength(); |
61 | | - } |
62 | | - bytesWritten += byteCount; |
63 | | - mProgressListener.onProgress( |
64 | | - bytesWritten, contentLength, bytesWritten == contentLength); |
65 | | - } |
66 | | - }; |
| 69 | + @Override |
| 70 | + public void write(int data) throws IOException { |
| 71 | + super.write(data); |
| 72 | + sendProgressUpdate(); |
| 73 | + } |
| 74 | + |
| 75 | + private void sendProgressUpdate() throws IOException { |
| 76 | + long bytesWritten = getCount(); |
| 77 | + long contentLength = contentLength(); |
| 78 | + mProgressListener.onProgress( |
| 79 | + bytesWritten, contentLength, bytesWritten == contentLength); |
| 80 | + } |
| 81 | + }); |
67 | 82 | } |
68 | 83 | } |
0 commit comments