11package com .RNFetchBlob ;
22
33import android .util .Base64 ;
4- import android .util .Log ;
54
65import com .facebook .react .bridge .Arguments ;
76import com .facebook .react .bridge .ReactApplicationContext ;
1312import java .io .ByteArrayInputStream ;
1413import java .io .File ;
1514import java .io .FileInputStream ;
16- import java .io .FileNotFoundException ;
1715import java .io .FileOutputStream ;
1816import java .io .IOException ;
1917import java .io .InputStream ;
20- import java .nio .ByteBuffer ;
21- import java .nio .MappedByteBuffer ;
2218import java .util .ArrayList ;
23- import java .util .HashMap ;
2419
2520import okhttp3 .MediaType ;
2621import okhttp3 .RequestBody ;
27- import okhttp3 .FormBody ;
28- import okio .Buffer ;
2922import 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