|  | @@ -8,6 +8,7 @@ import android.os.Environment;
 | 
	
		
			
			| 8 | 8 |  
 | 
	
		
			
			| 9 | 9 |  import com.facebook.react.bridge.Arguments;
 | 
	
		
			
			| 10 | 10 |  import com.facebook.react.bridge.Callback;
 | 
	
		
			
			|  | 11 | +import com.facebook.react.bridge.Promise;
 | 
	
		
			
			| 11 | 12 |  import com.facebook.react.bridge.ReactApplicationContext;
 | 
	
		
			
			| 12 | 13 |  import com.facebook.react.bridge.ReadableArray;
 | 
	
		
			
			| 13 | 14 |  import com.facebook.react.bridge.ReadableMap;
 | 
	
	
		
			
			|  | @@ -18,6 +19,7 @@ import com.loopj.android.http.Base64;
 | 
	
		
			
			| 18 | 19 |  
 | 
	
		
			
			| 19 | 20 |  import java.io.File;
 | 
	
		
			
			| 20 | 21 |  import java.io.FileInputStream;
 | 
	
		
			
			|  | 22 | +import java.io.FileNotFoundException;
 | 
	
		
			
			| 21 | 23 |  import java.io.FileOutputStream;
 | 
	
		
			
			| 22 | 24 |  import java.io.IOException;
 | 
	
		
			
			| 23 | 25 |  import java.io.InputStream;
 | 
	
	
		
			
			|  | @@ -25,9 +27,11 @@ import java.io.OutputStream;
 | 
	
		
			
			| 25 | 27 |  import java.io.OutputStreamWriter;
 | 
	
		
			
			| 26 | 28 |  import java.nio.charset.Charset;
 | 
	
		
			
			| 27 | 29 |  import java.nio.charset.StandardCharsets;
 | 
	
		
			
			|  | 30 | +import java.util.ArrayList;
 | 
	
		
			
			| 28 | 31 |  import java.util.HashMap;
 | 
	
		
			
			| 29 | 32 |  import java.util.Map;
 | 
	
		
			
			| 30 | 33 |  import java.util.UUID;
 | 
	
		
			
			|  | 34 | +import java.util.concurrent.ExecutionException;
 | 
	
		
			
			| 31 | 35 |  
 | 
	
		
			
			| 32 | 36 |  import cz.msebera.android.httpclient.util.EncodingUtils;
 | 
	
		
			
			| 33 | 37 |  
 | 
	
	
		
			
			|  | @@ -48,6 +52,113 @@ public class RNFetchBlobFS {
 | 
	
		
			
			| 48 | 52 |          this.emitter = ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
 | 
	
		
			
			| 49 | 53 |      }
 | 
	
		
			
			| 50 | 54 |  
 | 
	
		
			
			|  | 55 | +    /**
 | 
	
		
			
			|  | 56 | +     * Write string with encoding to file
 | 
	
		
			
			|  | 57 | +     * @param path Destination file path.
 | 
	
		
			
			|  | 58 | +     * @param encoding Encoding of the string.
 | 
	
		
			
			|  | 59 | +     * @param data Array passed from JS context.
 | 
	
		
			
			|  | 60 | +     * @param promise
 | 
	
		
			
			|  | 61 | +     */
 | 
	
		
			
			|  | 62 | +    static public void writeFile(String path, String encoding, String data, final Promise promise) {
 | 
	
		
			
			|  | 63 | +        AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
 | 
	
		
			
			|  | 64 | +            @Override
 | 
	
		
			
			|  | 65 | +            protected Integer doInBackground(String... args) {
 | 
	
		
			
			|  | 66 | +                String path = args[0];
 | 
	
		
			
			|  | 67 | +                String encoding = args[1];
 | 
	
		
			
			|  | 68 | +                String data = args[2];
 | 
	
		
			
			|  | 69 | +                File f = new File(path);
 | 
	
		
			
			|  | 70 | +                try {
 | 
	
		
			
			|  | 71 | +                    FileOutputStream fout = new FileOutputStream(f);
 | 
	
		
			
			|  | 72 | +                    fout.write(stringToBytes(data, encoding));
 | 
	
		
			
			|  | 73 | +                    fout.close();
 | 
	
		
			
			|  | 74 | +                    promise.resolve(null);
 | 
	
		
			
			|  | 75 | +                } catch (Exception e) {
 | 
	
		
			
			|  | 76 | +                    promise.reject("RNFetchBlob writeFileError", e.getLocalizedMessage());
 | 
	
		
			
			|  | 77 | +                }
 | 
	
		
			
			|  | 78 | +                return null;
 | 
	
		
			
			|  | 79 | +            }
 | 
	
		
			
			|  | 80 | +        };
 | 
	
		
			
			|  | 81 | +        task.execute(path, encoding, data);
 | 
	
		
			
			|  | 82 | +    }
 | 
	
		
			
			|  | 83 | +
 | 
	
		
			
			|  | 84 | +    /**
 | 
	
		
			
			|  | 85 | +     * Write array of bytes into file
 | 
	
		
			
			|  | 86 | +     * @param path Destination file path.
 | 
	
		
			
			|  | 87 | +     * @param data Array passed from JS context.
 | 
	
		
			
			|  | 88 | +     * @param promise
 | 
	
		
			
			|  | 89 | +     */
 | 
	
		
			
			|  | 90 | +    static public void writeFile(String path, ReadableArray data, final Promise promise) {
 | 
	
		
			
			|  | 91 | +        AsyncTask<Object, Integer, Integer> task = new AsyncTask<Object, Integer, Integer>() {
 | 
	
		
			
			|  | 92 | +            @Override
 | 
	
		
			
			|  | 93 | +            protected Integer doInBackground(Object... args) {
 | 
	
		
			
			|  | 94 | +                String path = String.valueOf(args[0]);
 | 
	
		
			
			|  | 95 | +                ReadableArray data = (ReadableArray) args[2];
 | 
	
		
			
			|  | 96 | +                File f = new File(path);
 | 
	
		
			
			|  | 97 | +                try {
 | 
	
		
			
			|  | 98 | +                    FileOutputStream os = new FileOutputStream(f);
 | 
	
		
			
			|  | 99 | +                    byte [] bytes = new byte[data.size()];
 | 
	
		
			
			|  | 100 | +                    for(int i=0;i<data.size();i++) {
 | 
	
		
			
			|  | 101 | +                        bytes[i] = (byte) data.getInt(i);
 | 
	
		
			
			|  | 102 | +                    }
 | 
	
		
			
			|  | 103 | +                    os.write(bytes);
 | 
	
		
			
			|  | 104 | +                    os.close();
 | 
	
		
			
			|  | 105 | +                    promise.resolve(null);
 | 
	
		
			
			|  | 106 | +                } catch (Exception e) {
 | 
	
		
			
			|  | 107 | +                    promise.reject("RNFetchBlob writeFileError", e.getLocalizedMessage());
 | 
	
		
			
			|  | 108 | +                }
 | 
	
		
			
			|  | 109 | +                return null;
 | 
	
		
			
			|  | 110 | +            }
 | 
	
		
			
			|  | 111 | +        };
 | 
	
		
			
			|  | 112 | +        task.execute(path, data);
 | 
	
		
			
			|  | 113 | +    }
 | 
	
		
			
			|  | 114 | +
 | 
	
		
			
			|  | 115 | +    /**
 | 
	
		
			
			|  | 116 | +     * Read file with a buffer that has the same size as the target file.
 | 
	
		
			
			|  | 117 | +     * @param path  Path of the file.
 | 
	
		
			
			|  | 118 | +     * @param encoding  Encoding of read stream.
 | 
	
		
			
			|  | 119 | +     * @param promise
 | 
	
		
			
			|  | 120 | +     */
 | 
	
		
			
			|  | 121 | +    static public void readFile(String path, String encoding, final Promise promise ) {
 | 
	
		
			
			|  | 122 | +        AsyncTask task = new AsyncTask<String, Integer, Integer>() {
 | 
	
		
			
			|  | 123 | +            @Override
 | 
	
		
			
			|  | 124 | +            protected Integer doInBackground(String... strings) {
 | 
	
		
			
			|  | 125 | +                try {
 | 
	
		
			
			|  | 126 | +                    String path = strings[0];
 | 
	
		
			
			|  | 127 | +                    String encoding = strings[1];
 | 
	
		
			
			|  | 128 | +                    File f = new File(path);
 | 
	
		
			
			|  | 129 | +                    int length = (int) f.length();
 | 
	
		
			
			|  | 130 | +                    byte[] bytes = new byte[length];
 | 
	
		
			
			|  | 131 | +                    FileInputStream in = new FileInputStream(f);
 | 
	
		
			
			|  | 132 | +                    in.read(bytes);
 | 
	
		
			
			|  | 133 | +                    in.close();
 | 
	
		
			
			|  | 134 | +                    switch (encoding.toLowerCase()) {
 | 
	
		
			
			|  | 135 | +                        case "base64" :
 | 
	
		
			
			|  | 136 | +                            promise.resolve(Base64.encodeToString(bytes, 0));
 | 
	
		
			
			|  | 137 | +                            break;
 | 
	
		
			
			|  | 138 | +                        case "ascii" :
 | 
	
		
			
			|  | 139 | +                            WritableArray asciiResult = Arguments.createArray();
 | 
	
		
			
			|  | 140 | +                            for(byte b : bytes) {
 | 
	
		
			
			|  | 141 | +                                asciiResult.pushInt((int)b);
 | 
	
		
			
			|  | 142 | +                            }
 | 
	
		
			
			|  | 143 | +                            promise.resolve(bytes);
 | 
	
		
			
			|  | 144 | +                            break;
 | 
	
		
			
			|  | 145 | +                        case "utf8" :
 | 
	
		
			
			|  | 146 | +                            promise.resolve(new String(bytes));
 | 
	
		
			
			|  | 147 | +                            break;
 | 
	
		
			
			|  | 148 | +                        default:
 | 
	
		
			
			|  | 149 | +                            promise.resolve(new String(bytes));
 | 
	
		
			
			|  | 150 | +                            break;
 | 
	
		
			
			|  | 151 | +                    }
 | 
	
		
			
			|  | 152 | +                }
 | 
	
		
			
			|  | 153 | +                catch(Exception err) {
 | 
	
		
			
			|  | 154 | +                    promise.reject("ReadFile Error", err.getLocalizedMessage());
 | 
	
		
			
			|  | 155 | +                }
 | 
	
		
			
			|  | 156 | +                return null;
 | 
	
		
			
			|  | 157 | +            }
 | 
	
		
			
			|  | 158 | +        };
 | 
	
		
			
			|  | 159 | +        task.execute(path, encoding);
 | 
	
		
			
			|  | 160 | +    }
 | 
	
		
			
			|  | 161 | +
 | 
	
		
			
			| 51 | 162 |      /**
 | 
	
		
			
			| 52 | 163 |       * Static method that returns system folders to JS context
 | 
	
		
			
			| 53 | 164 |       * @param ctx   React Native application context
 | 
	
	
		
			
			|  | @@ -106,14 +217,11 @@ public class RNFetchBlobFS {
 | 
	
		
			
			| 106 | 217 |                          }
 | 
	
		
			
			| 107 | 218 |                      } else if (encoding.equalsIgnoreCase("ascii")) {
 | 
	
		
			
			| 108 | 219 |                          while ((cursor = fs.read(buffer)) != -1) {
 | 
	
		
			
			| 109 |  | -                            String chunk = "[";
 | 
	
		
			
			|  | 220 | +                            WritableArray chunk = Arguments.createArray();
 | 
	
		
			
			| 110 | 221 |                              for(int i =0;i<cursor;i++)
 | 
	
		
			
			| 111 | 222 |                              {
 | 
	
		
			
			| 112 |  | -                                chunk += (int)buffer[i];
 | 
	
		
			
			| 113 |  | -                                if(i+1 < cursor)
 | 
	
		
			
			| 114 |  | -                                    chunk += ",";
 | 
	
		
			
			|  | 223 | +                                chunk.pushInt((int)buffer[i]);
 | 
	
		
			
			| 115 | 224 |                              }
 | 
	
		
			
			| 116 |  | -                            chunk = chunk + "]";
 | 
	
		
			
			| 117 | 225 |                              emitStreamEvent(eventName, "data", chunk);
 | 
	
		
			
			| 118 | 226 |                          }
 | 
	
		
			
			| 119 | 227 |                      } else if (encoding.equalsIgnoreCase("base64")) {
 | 
	
	
		
			
			|  | @@ -530,6 +638,13 @@ public class RNFetchBlobFS {
 | 
	
		
			
			| 530 | 638 |          this.emitter.emit(streamName, eventData);
 | 
	
		
			
			| 531 | 639 |      }
 | 
	
		
			
			| 532 | 640 |  
 | 
	
		
			
			|  | 641 | +    void emitStreamEvent(String streamName, String event, WritableArray  data) {
 | 
	
		
			
			|  | 642 | +        WritableMap eventData = Arguments.createMap();
 | 
	
		
			
			|  | 643 | +        eventData.putString("event", event);
 | 
	
		
			
			|  | 644 | +        eventData.putArray("detail", data);
 | 
	
		
			
			|  | 645 | +        this.emitter.emit(streamName, eventData);
 | 
	
		
			
			|  | 646 | +    }
 | 
	
		
			
			|  | 647 | +
 | 
	
		
			
			| 533 | 648 |      // TODO : should we remove this ?
 | 
	
		
			
			| 534 | 649 |      void emitFSData(String taskId, String event, String data) {
 | 
	
		
			
			| 535 | 650 |          WritableMap eventData = Arguments.createMap();
 |