Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions android/src/main/java/com/rnfs/RNFSManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
Expand All @@ -30,6 +31,7 @@
import java.io.RandomAccessFile;
import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -47,6 +49,8 @@ public class RNFSManager extends ReactContextBaseJavaModule {
private static final String RNFSFileTypeDirectory = "RNFSFileTypeDirectory";

private SparseArray<Downloader> downloaders = new SparseArray<Downloader>();
private SparseArray<Uploader> uploaders = new SparseArray<Uploader>();

private ReactApplicationContext reactContext;

public RNFSManager(ReactApplicationContext reactContext) {
Expand Down Expand Up @@ -665,6 +669,84 @@ public void stopDownload(int jobId) {
}
}

@ReactMethod
public void uploadFiles(final ReadableMap options, final Promise promise) {
try {
ReadableArray files = options.getArray("files");
URL url = new URL(options.getString("toUrl"));
final int jobId = options.getInt("jobId");
ReadableMap headers = options.getMap("headers");
ReadableMap fields = options.getMap("fields");
String method = options.getString("method");
ArrayList<ReadableMap> fileList = new ArrayList<>();
UploadParams params = new UploadParams();
for(int i =0;i<files.size();i++){
fileList.add(files.getMap(i));
}
params.src = url;
params.files =fileList;
params.headers = headers;
params.method=method;
params.fields=fields;
params.onUploadComplete = new UploadParams.onUploadComplete() {
public void onUploadComplete(UploadResult res) {
if (res.exception == null) {
WritableMap infoMap = Arguments.createMap();

infoMap.putInt("jobId", jobId);
infoMap.putInt("statusCode", res.statusCode);
infoMap.putMap("headers",res.headers);
infoMap.putString("body",res.body);
promise.resolve(infoMap);
} else {
reject(promise, options.getString("toUrl"), res.exception);
}
}
};

params.onUploadBegin = new UploadParams.onUploadBegin() {
public void onUploadBegin() {
WritableMap data = Arguments.createMap();

data.putInt("jobId", jobId);

sendEvent(getReactApplicationContext(), "UploadBegin-" + jobId, data);
}
};

params.onUploadProgress = new UploadParams.onUploadProgress() {
public void onUploadProgress(int fileCount,int totalBytesExpectedToSend,int totalBytesSent) {
WritableMap data = Arguments.createMap();

data.putInt("jobId", jobId);
data.putInt("FileID",fileCount);
data.putInt("totalBytesExpectedToSend", totalBytesExpectedToSend);
data.putInt("totalBytesSent", totalBytesSent);

sendEvent(getReactApplicationContext(), "UploadProgress-" + jobId, data);
}
};

Uploader uploader = new Uploader();

uploader.execute(params);

this.uploaders.put(jobId, uploader);
} catch (Exception ex) {
ex.printStackTrace();
reject(promise, options.getString("toUrl"), ex);
}
}

@ReactMethod
public void stopUpload(int jobId) {
Uploader uploader = this.uploaders.get(jobId);

if (uploader != null) {
uploader.stop();
}
}

@ReactMethod
public void pathForBundle(String bundleNamed, Promise promise) {
// TODO: Not sure what equivalent would be?
Expand Down
27 changes: 27 additions & 0 deletions android/src/main/java/com/rnfs/UploadParams.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.rnfs;

import com.facebook.react.bridge.ReadableMap;

import java.net.URL;
import java.util.ArrayList;

public class UploadParams {
public interface onUploadComplete{
void onUploadComplete(UploadResult res);
}
public interface onUploadProgress{
void onUploadProgress(int fileCount,int totalBytesExpectedToSend,int totalBytesSent);
}
public interface onUploadBegin{
void onUploadBegin();
}
public URL src;
public ArrayList<ReadableMap> files;
public String name;
public ReadableMap headers;
public ReadableMap fields;
public String method;
public onUploadComplete onUploadComplete;
public onUploadProgress onUploadProgress;
public onUploadBegin onUploadBegin;
}
10 changes: 10 additions & 0 deletions android/src/main/java/com/rnfs/UploadResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.rnfs;

import com.facebook.react.bridge.WritableMap;

public class UploadResult {
public int statusCode;
public WritableMap headers;
public Exception exception;
public String body;
}
178 changes: 178 additions & 0 deletions android/src/main/java/com/rnfs/Uploader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package com.rnfs;

import android.os.AsyncTask;
import android.webkit.MimeTypeMap;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.NoSuchKeyException;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public class Uploader extends AsyncTask<UploadParams, int[], UploadResult> {
private UploadParams mParams;
private UploadResult res;
private AtomicBoolean mAbort = new AtomicBoolean(false);

@Override
protected UploadResult doInBackground(UploadParams... uploadParams) {
mParams = uploadParams[0];
res = new UploadResult();
new Thread(new Runnable() {
@Override
public void run() {
try {
upload(mParams, res);
mParams.onUploadComplete.onUploadComplete(res);
} catch (Exception e) {
res.exception = e;
mParams.onUploadComplete.onUploadComplete(res);
}
}
}).start();
return res;
}

private void upload(UploadParams params, UploadResult result) throws Exception {
HttpURLConnection connection = null;
DataOutputStream request = null;
String crlf = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int Readed, bufferSize, totalSize, byteRead, statusCode, bufferAvailable;
int fileCount = 1;
BufferedInputStream responseStream = null;
BufferedReader responseStreamReader = null;
int maxBufferSize = 1 * 1024 * 1024;
String name, filename, filetype;
Map<String, List<String>> responseHeader;
try {
connection = (HttpURLConnection) params.src.openConnection();
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setDoInput(true);
ReadableMapKeySetIterator headerIterator = params.headers.keySetIterator();
connection.setRequestMethod(params.method);
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
while (headerIterator.hasNextKey()) {
String key = headerIterator.nextKey();
String value = params.headers.getString(key);
connection.setRequestProperty(key, value);
}

request = new DataOutputStream(connection.getOutputStream());

ReadableMapKeySetIterator fieldsIterator = params.fields.keySetIterator();

while (fieldsIterator.hasNextKey()) {
request.writeBytes(twoHyphens + boundary + crlf);
String key = fieldsIterator.nextKey();
String value = params.fields.getString(key);
request.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"" + crlf);
request.writeBytes(crlf);
request.writeBytes(value);
request.writeBytes(crlf);
}
mParams.onUploadBegin.onUploadBegin();
for (ReadableMap map : params.files) {
try {
name = map.getString("name");
filename = map.getString("filename");
filetype = map.getString("filetype");
} catch (NoSuchKeyException e) {
name = map.getString("filename");
filename = map.getString("filename");
filetype = getMimeType(map.getString("filepath"));
}
request.writeBytes(twoHyphens + boundary + crlf);
File file = new File(map.getString("filepath"));
request.writeBytes(
"Content-Disposition: form-data; name=\"" + name + "\";filename=\"" + filename + "\"" + crlf);
request.writeBytes("Content-Type: " + filetype + crlf);
request.writeBytes(crlf);
byte[] b = new byte[(int) file.length()];

FileInputStream fileInputStream = new FileInputStream(file);

Readed = 0;
bufferAvailable = 4096;
bufferSize = Math.min(bufferAvailable, maxBufferSize);
byteRead = fileInputStream.read(b, 0, bufferSize);
totalSize = b.length;
Readed += byteRead;
while (byteRead > 0) {
if (mAbort.get())
throw new Exception("Upload has been aborted");
request.write(b, 0, bufferSize);
byteRead = fileInputStream.read(b, 0, bufferSize);
if (byteRead == -1) {
mParams.onUploadProgress.onUploadProgress(fileCount, totalSize, Readed);
} else {
Readed += byteRead;
mParams.onUploadProgress.onUploadProgress(fileCount, totalSize, Readed);
}
}
request.writeBytes(crlf);
fileCount++;
}
request.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
request.flush();

responseStream = new BufferedInputStream(connection.getInputStream());
responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
WritableMap responseHeaders = Arguments.createMap();
Map<String, List<String>> map = connection.getHeaderFields();
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
int count = 0;
responseHeaders.putString(entry.getKey(), entry.getValue().get(count));
}
StringBuilder stringBuilder = new StringBuilder();
String line = "";

while ((line = responseStreamReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}

String response = stringBuilder.toString();
statusCode = connection.getResponseCode();
res.headers = responseHeaders;
res.body = response;
res.statusCode = statusCode;
} finally {
if (connection != null)
connection.disconnect();
if (request != null)
request.close();
if (responseStream != null)
responseStream.close();
if (responseStreamReader != null)
responseStreamReader.close();
}
}

protected String getMimeType(String path) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(path);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}

protected void stop() {
mAbort.set(true);
}

}