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

Commit 2a7ca8d

Browse files
committed
Merge remote-tracking branch 'wkh237/feat_45' into feat_45
* wkh237/feat_45: Add test cases #45 Fix IOS ALAsset upload issue #45 Add test cases for #45 Fix cp and stat for assets #45 Add #45 Android implementation
2 parents 2ad9ab2 + a1b398b commit 2a7ca8d

File tree

15 files changed

+634
-284
lines changed

15 files changed

+634
-284
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
public class RNFetchBlob extends ReactContextBaseJavaModule {
1414

1515
String filePathPrefix = "RNFetchBlob-file://";
16+
static ReactApplicationContext RCTContext;
1617

1718
public RNFetchBlob(ReactApplicationContext reactContext) {
19+
1820
super(reactContext);
21+
RCTContext = reactContext;
1922
}
2023

2124
@Override

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

Lines changed: 160 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
package com.RNFetchBlob;
22

3+
import android.app.Application;
4+
import android.content.CursorLoader;
35
import android.content.Intent;
6+
import android.content.res.AssetFileDescriptor;
7+
import android.content.res.AssetManager;
8+
import android.database.Cursor;
49
import android.media.MediaScannerConnection;
510
import android.net.Uri;
611
import android.os.AsyncTask;
712
import android.os.Environment;
13+
import android.provider.MediaStore;
814

915
import com.facebook.react.bridge.Arguments;
1016
import com.facebook.react.bridge.Callback;
@@ -43,6 +49,7 @@ public class RNFetchBlobFS {
4349
ReactApplicationContext mCtx;
4450
DeviceEventManagerModule.RCTDeviceEventEmitter emitter;
4551
String encoding = "base64";
52+
static final String assetPrefix = "bundle-assets://";
4653
boolean append = false;
4754
OutputStream writeStreamInstance = null;
4855
static HashMap<String, RNFetchBlobFS> fileStreams = new HashMap<>();
@@ -134,19 +141,33 @@ protected Void doInBackground(Object... args) {
134141
* @param promise
135142
*/
136143
static public void readFile(String path, String encoding, final Promise promise ) {
144+
path = normalizePath(path);
137145
AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
138146
@Override
139147
protected Integer doInBackground(String... strings) {
140148

141149
try {
142150
String path = strings[0];
143151
String encoding = strings[1];
144-
File f = new File(path);
145-
int length = (int) f.length();
146-
byte[] bytes = new byte[length];
147-
FileInputStream in = new FileInputStream(f);
148-
in.read(bytes);
149-
in.close();
152+
byte[] bytes;
153+
154+
if(path.startsWith(assetPrefix)) {
155+
String assetName = path.replace(assetPrefix, "");
156+
long length = RNFetchBlob.RCTContext.getAssets().openFd(assetName).getLength();
157+
bytes = new byte[(int) length];
158+
InputStream in = RNFetchBlob.RCTContext.getAssets().open(assetName);
159+
in.read(bytes, 0, (int) length);
160+
in.close();
161+
}
162+
else {
163+
File f = new File(path);
164+
int length = (int) f.length();
165+
bytes = new byte[length];
166+
FileInputStream in = new FileInputStream(f);
167+
in.read(bytes);
168+
in.close();
169+
}
170+
150171
switch (encoding.toLowerCase()) {
151172
case "base64" :
152173
promise.resolve(Base64.encodeToString(bytes, 0));
@@ -209,6 +230,7 @@ static public String getTmpPath(ReactApplicationContext ctx, String taskId) {
209230
* @param bufferSize Buffer size of read stream, default to 4096 (4095 when encode is `base64`)
210231
*/
211232
public void readStream( String path, String encoding, int bufferSize) {
233+
path = normalizePath(path);
212234
AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
213235
@Override
214236
protected Integer doInBackground(String ... args) {
@@ -221,7 +243,15 @@ protected Integer doInBackground(String ... args) {
221243
int chunkSize = encoding.equalsIgnoreCase("base64") ? 4095 : 4096;
222244
if(bufferSize > 0)
223245
chunkSize = bufferSize;
224-
FileInputStream fs = new FileInputStream(new File(path));
246+
247+
InputStream fs;
248+
if(path.startsWith(assetPrefix)) {
249+
fs = RNFetchBlob.RCTContext.getAssets().open(path.replace(assetPrefix, ""));
250+
}
251+
else {
252+
fs = new FileInputStream(new File(path));
253+
}
254+
225255
byte[] buffer = new byte[chunkSize];
226256
int cursor = 0;
227257
boolean error = false;
@@ -314,7 +344,6 @@ static void writeChunk(String streamId, String data, Callback callback) {
314344
try {
315345
stream.write(chunk);
316346
callback.invoke();
317-
chunk = null;
318347
} catch (Exception e) {
319348
callback.invoke(e.getLocalizedMessage());
320349
}
@@ -344,7 +373,7 @@ static void writeArrayChunk(String streamId, ReadableArray data, Callback callba
344373
}
345374

346375
/**
347-
* Close file stream by ID
376+
* Close file write stream by ID
348377
* @param streamId Stream ID
349378
* @param callback JS context callback
350379
*/
@@ -395,21 +424,21 @@ static void mkdir(String path, Callback callback) {
395424
* @param callback JS context callback
396425
*/
397426
static void cp(String path, String dest, Callback callback) {
427+
path = normalizePath(path);
398428
InputStream in = null;
399429
OutputStream out = null;
400430

401431
try {
402432

403-
String destFolder = new File(dest).getPath();
404-
if(!new File(path).exists()) {
433+
if(!isPathExists(path)) {
405434
callback.invoke("cp error: source file at path`" + path + "` not exists");
406435
return;
407436
}
408437

409438
if(!new File(dest).exists())
410439
new File(dest).createNewFile();
411440

412-
in = new FileInputStream(path);
441+
in = inputStreamFromPath(path);
413442
out = new FileOutputStream(dest);
414443

415444
byte[] buf = new byte[1024];
@@ -454,9 +483,22 @@ static void mv(String path, String dest, Callback callback) {
454483
* @param callback JS context callback
455484
*/
456485
static void exists(String path, Callback callback) {
457-
boolean exist = new File(path).exists();
458-
boolean isDir = new File(path).isDirectory();;
459-
callback.invoke(exist, isDir);
486+
path = normalizePath(path);
487+
if(isAsset(path)) {
488+
try {
489+
String filename = path.replace(assetPrefix, "");
490+
AssetFileDescriptor fd = RNFetchBlob.RCTContext.getAssets().openFd(filename);
491+
callback.invoke(true, false);
492+
} catch (IOException e) {
493+
callback.invoke(false, false);
494+
}
495+
}
496+
else {
497+
boolean exist = new File(path).exists();
498+
boolean isDir = new File(path).isDirectory();
499+
callback.invoke(exist, isDir);
500+
}
501+
460502
}
461503

462504
/**
@@ -465,21 +507,23 @@ static void exists(String path, Callback callback) {
465507
* @param callback JS context callback
466508
*/
467509
static void ls(String path, Callback callback) {
510+
path = normalizePath(path);
468511
File src = new File(path);
469-
if(!src.exists() || !src.isDirectory()) {
512+
if (!src.exists() || !src.isDirectory()) {
470513
callback.invoke("ls error: failed to list path `" + path + "` for it is not exist or it is not a folder");
471514
return;
472515
}
473-
String [] files = new File(path).list();
516+
String[] files = new File(path).list();
474517
WritableArray arg = Arguments.createArray();
475-
for(String i : files) {
518+
for (String i : files) {
476519
arg.pushString(i);
477520
}
478521
callback.invoke(null, arg);
479522
}
480523

481524
static void lstat(String path, final Callback callback) {
482-
File src = new File(path);
525+
path = normalizePath(path);
526+
483527
new AsyncTask<String, Integer, Integer>() {
484528
@Override
485529
protected Integer doInBackground(String ...args) {
@@ -511,24 +555,55 @@ protected Integer doInBackground(String ...args) {
511555
*/
512556
static void stat(String path, Callback callback) {
513557
try {
514-
File target = new File(path);
515-
if (!target.exists()) {
516-
callback.invoke("stat error: file " + path + " does not exists");
517-
return;
518-
}
519-
WritableMap stat = Arguments.createMap();
520-
stat.putString("filename", target.getName());
521-
stat.putString("path", target.getPath());
522-
stat.putString("type", target.isDirectory() ? "directory" : "file");
523-
stat.putString("size", String.valueOf(target.length()));
524-
String lastModified = String.valueOf(target.lastModified());
525-
stat.putString("lastModified", lastModified);
526-
callback.invoke(null, stat);
558+
callback.invoke(null, statFile(path));
527559
} catch(Exception err) {
528560
callback.invoke(err.getLocalizedMessage());
529561
}
530562
}
531563

564+
/**
565+
* Basic stat method
566+
* @param path
567+
* @return Stat result of a file or path
568+
*/
569+
static WritableMap statFile(String path) {
570+
try {
571+
path = normalizePath(path);
572+
WritableMap stat = Arguments.createMap();
573+
if(isAsset(path)) {
574+
String name = path.replace(assetPrefix, "");
575+
AssetFileDescriptor fd = RNFetchBlob.RCTContext.getAssets().openFd(name);
576+
stat.putString("filename", name);
577+
stat.putString("path", path);
578+
stat.putString("type", "asset");
579+
stat.putString("size", String.valueOf(fd.getLength()));
580+
stat.putString("lastModified", "0");
581+
}
582+
else {
583+
File target = new File(path);
584+
if (!target.exists()) {
585+
return null;
586+
}
587+
stat.putString("filename", target.getName());
588+
stat.putString("path", target.getPath());
589+
stat.putString("type", target.isDirectory() ? "directory" : "file");
590+
stat.putString("size", String.valueOf(target.length()));
591+
String lastModified = String.valueOf(target.lastModified());
592+
stat.putString("lastModified", lastModified);
593+
594+
}
595+
return stat;
596+
} catch(Exception err) {
597+
return null;
598+
}
599+
}
600+
601+
/**
602+
* Media scanner scan file
603+
* @param path
604+
* @param mimes
605+
* @param callback
606+
*/
532607
void scanFile(String [] path, String[] mimes, final Callback callback) {
533608
try {
534609
MediaScannerConnection.scanFile(mCtx, path, mimes, new MediaScannerConnection.OnScanCompletedListener() {
@@ -669,18 +744,60 @@ void emitFSData(String taskId, String event, String data) {
669744
this.emitter.emit("RNFetchBlobStream" + taskId, eventData);
670745
}
671746

672-
static WritableMap statFile(String path) {
673-
File target = new File(path);
674-
if(!target.exists()) {
675-
return null;
747+
/**
748+
* Get input stream of the given path, when the path is a string starts with bundle-assets://
749+
* the stream is created by Assets Manager, otherwise use FileInputStream.
750+
* @param path
751+
* @return
752+
* @throws IOException
753+
*/
754+
static InputStream inputStreamFromPath(String path) throws IOException {
755+
if (path.startsWith(assetPrefix)) {
756+
return RNFetchBlob.RCTContext.getAssets().open(path.replace(assetPrefix, ""));
757+
}
758+
return new FileInputStream(new File(path));
759+
}
760+
761+
/**
762+
* Check if the asset or the file exists
763+
* @param path
764+
* @return
765+
*/
766+
static boolean isPathExists(String path) {
767+
if(path.startsWith(assetPrefix)) {
768+
try {
769+
RNFetchBlob.RCTContext.getAssets().open(path.replace(assetPrefix, ""));
770+
} catch (IOException e) {
771+
return false;
772+
}
773+
return true;
774+
}
775+
else {
776+
return new File(path).exists();
777+
}
778+
779+
}
780+
781+
static boolean isAsset(String path) {
782+
return path.startsWith(assetPrefix);
783+
}
784+
785+
static String normalizePath(String path) {
786+
if(path.startsWith("bundle-assets://")) {
787+
return path;
788+
}
789+
else if (path.startsWith("content://")) {
790+
String[] proj = { MediaStore.Images.Media.DATA };
791+
Uri contentUri = Uri.parse(path);
792+
CursorLoader loader = new CursorLoader(RNFetchBlob.RCTContext, contentUri, proj, null, null, null);
793+
Cursor cursor = loader.loadInBackground();
794+
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
795+
cursor.moveToFirst();
796+
String result = cursor.getString(column_index);
797+
cursor.close();
798+
return result;
676799
}
677-
WritableMap stat = Arguments.createMap();
678-
stat.putString("filename", target.getName());
679-
stat.putString("path", target.getPath());
680-
stat.putString("type", target.isDirectory() ? "directory" : "file");
681-
stat.putInt("size", (int)target.length());
682-
stat.putInt("lastModified", (int)target.lastModified());
683-
return stat;
800+
return path;
684801
}
685802

686803
}

src/fs.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import {
99
NativeModules,
1010
DeviceEventEmitter,
11+
Platform,
1112
NativeAppEventEmitter,
1213
} from 'react-native'
1314
import RNFetchBlobSession from './class/RNFetchBlobSession'
@@ -47,6 +48,15 @@ function session(name:string):RNFetchBlobSession {
4748
}
4849
}
4950

51+
function asset(path:string):string {
52+
if(Platform.OS === 'ios') {
53+
// path from camera roll
54+
if(/^assets-library\:\/\//.test(path))
55+
return path
56+
}
57+
return 'bundle-assets://' + path
58+
}
59+
5060
function createFile(path:string, data:string, encoding: 'base64' | 'ascii' | 'utf8'):Promise {
5161
encoding = encoding || 'utf8'
5262
return new Promise((resolve, reject) => {
@@ -324,5 +334,6 @@ export default {
324334
stat,
325335
lstat,
326336
scanFile,
327-
dirs
337+
dirs,
338+
asset
328339
}

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,5 +272,5 @@ export default {
272272
config,
273273
session,
274274
fs,
275-
wrap,
275+
wrap
276276
}

0 commit comments

Comments
 (0)