浏览代码

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
Erik Smartt 9 年前
父节点
当前提交
2a7ca8d311

+ 3
- 0
src/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java 查看文件

13
 public class RNFetchBlob extends ReactContextBaseJavaModule {
13
 public class RNFetchBlob extends ReactContextBaseJavaModule {
14
 
14
 
15
     String filePathPrefix = "RNFetchBlob-file://";
15
     String filePathPrefix = "RNFetchBlob-file://";
16
+    static ReactApplicationContext RCTContext;
16
 
17
 
17
     public RNFetchBlob(ReactApplicationContext reactContext) {
18
     public RNFetchBlob(ReactApplicationContext reactContext) {
19
+
18
         super(reactContext);
20
         super(reactContext);
21
+        RCTContext = reactContext;
19
     }
22
     }
20
 
23
 
21
     @Override
24
     @Override

+ 160
- 43
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java 查看文件

1
 package com.RNFetchBlob;
1
 package com.RNFetchBlob;
2
 
2
 
3
+import android.app.Application;
4
+import android.content.CursorLoader;
3
 import android.content.Intent;
5
 import android.content.Intent;
6
+import android.content.res.AssetFileDescriptor;
7
+import android.content.res.AssetManager;
8
+import android.database.Cursor;
4
 import android.media.MediaScannerConnection;
9
 import android.media.MediaScannerConnection;
5
 import android.net.Uri;
10
 import android.net.Uri;
6
 import android.os.AsyncTask;
11
 import android.os.AsyncTask;
7
 import android.os.Environment;
12
 import android.os.Environment;
13
+import android.provider.MediaStore;
8
 
14
 
9
 import com.facebook.react.bridge.Arguments;
15
 import com.facebook.react.bridge.Arguments;
10
 import com.facebook.react.bridge.Callback;
16
 import com.facebook.react.bridge.Callback;
43
     ReactApplicationContext mCtx;
49
     ReactApplicationContext mCtx;
44
     DeviceEventManagerModule.RCTDeviceEventEmitter emitter;
50
     DeviceEventManagerModule.RCTDeviceEventEmitter emitter;
45
     String encoding = "base64";
51
     String encoding = "base64";
52
+    static final String assetPrefix = "bundle-assets://";
46
     boolean append = false;
53
     boolean append = false;
47
     OutputStream writeStreamInstance = null;
54
     OutputStream writeStreamInstance = null;
48
     static HashMap<String, RNFetchBlobFS> fileStreams = new HashMap<>();
55
     static HashMap<String, RNFetchBlobFS> fileStreams = new HashMap<>();
134
      * @param promise
141
      * @param promise
135
      */
142
      */
136
     static public void readFile(String path, String encoding, final Promise promise ) {
143
     static public void readFile(String path, String encoding, final Promise promise ) {
144
+        path = normalizePath(path);
137
         AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
145
         AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
138
             @Override
146
             @Override
139
             protected Integer doInBackground(String... strings) {
147
             protected Integer doInBackground(String... strings) {
141
                 try {
149
                 try {
142
                     String path = strings[0];
150
                     String path = strings[0];
143
                     String encoding = strings[1];
151
                     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
+
150
                     switch (encoding.toLowerCase()) {
171
                     switch (encoding.toLowerCase()) {
151
                         case "base64" :
172
                         case "base64" :
152
                             promise.resolve(Base64.encodeToString(bytes, 0));
173
                             promise.resolve(Base64.encodeToString(bytes, 0));
209
      * @param bufferSize    Buffer size of read stream, default to 4096 (4095 when encode is `base64`)
230
      * @param bufferSize    Buffer size of read stream, default to 4096 (4095 when encode is `base64`)
210
      */
231
      */
211
     public void readStream( String path, String encoding, int bufferSize) {
232
     public void readStream( String path, String encoding, int bufferSize) {
233
+        path = normalizePath(path);
212
         AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
234
         AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
213
             @Override
235
             @Override
214
             protected Integer doInBackground(String ... args) {
236
             protected Integer doInBackground(String ... args) {
221
                     int chunkSize = encoding.equalsIgnoreCase("base64") ? 4095 : 4096;
243
                     int chunkSize = encoding.equalsIgnoreCase("base64") ? 4095 : 4096;
222
                     if(bufferSize > 0)
244
                     if(bufferSize > 0)
223
                         chunkSize = bufferSize;
245
                         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
+
225
                     byte[] buffer = new byte[chunkSize];
255
                     byte[] buffer = new byte[chunkSize];
226
                     int cursor = 0;
256
                     int cursor = 0;
227
                     boolean error = false;
257
                     boolean error = false;
314
         try {
344
         try {
315
             stream.write(chunk);
345
             stream.write(chunk);
316
             callback.invoke();
346
             callback.invoke();
317
-            chunk = null;
318
         } catch (Exception e) {
347
         } catch (Exception e) {
319
             callback.invoke(e.getLocalizedMessage());
348
             callback.invoke(e.getLocalizedMessage());
320
         }
349
         }
344
     }
373
     }
345
 
374
 
346
     /**
375
     /**
347
-     * Close file stream by ID
376
+     * Close file write stream by ID
348
      * @param streamId Stream ID
377
      * @param streamId Stream ID
349
      * @param callback JS context callback
378
      * @param callback JS context callback
350
      */
379
      */
395
      * @param callback  JS context callback
424
      * @param callback  JS context callback
396
      */
425
      */
397
     static void cp(String path, String dest, Callback callback) {
426
     static void cp(String path, String dest, Callback callback) {
427
+        path = normalizePath(path);
398
         InputStream in = null;
428
         InputStream in = null;
399
         OutputStream out = null;
429
         OutputStream out = null;
400
 
430
 
401
         try {
431
         try {
402
 
432
 
403
-            String destFolder = new File(dest).getPath();
404
-            if(!new File(path).exists()) {
433
+            if(!isPathExists(path)) {
405
                 callback.invoke("cp error: source file at path`" + path + "` not exists");
434
                 callback.invoke("cp error: source file at path`" + path + "` not exists");
406
                 return;
435
                 return;
407
             }
436
             }
409
             if(!new File(dest).exists())
438
             if(!new File(dest).exists())
410
                 new File(dest).createNewFile();
439
                 new File(dest).createNewFile();
411
 
440
 
412
-            in = new FileInputStream(path);
441
+            in = inputStreamFromPath(path);
413
             out = new FileOutputStream(dest);
442
             out = new FileOutputStream(dest);
414
 
443
 
415
             byte[] buf = new byte[1024];
444
             byte[] buf = new byte[1024];
454
      * @param callback  JS context callback
483
      * @param callback  JS context callback
455
      */
484
      */
456
     static void exists(String path, Callback callback) {
485
     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
+
460
     }
502
     }
461
 
503
 
462
     /**
504
     /**
465
      * @param callback  JS context callback
507
      * @param callback  JS context callback
466
      */
508
      */
467
     static void ls(String path, Callback callback) {
509
     static void ls(String path, Callback callback) {
510
+        path = normalizePath(path);
468
         File src = new File(path);
511
         File src = new File(path);
469
-        if(!src.exists() || !src.isDirectory()) {
512
+        if (!src.exists() || !src.isDirectory()) {
470
             callback.invoke("ls error: failed to list path `" + path + "` for it is not exist or it is not a folder");
513
             callback.invoke("ls error: failed to list path `" + path + "` for it is not exist or it is not a folder");
471
             return;
514
             return;
472
         }
515
         }
473
-        String [] files = new File(path).list();
516
+        String[] files = new File(path).list();
474
         WritableArray arg = Arguments.createArray();
517
         WritableArray arg = Arguments.createArray();
475
-        for(String i : files) {
518
+        for (String i : files) {
476
             arg.pushString(i);
519
             arg.pushString(i);
477
         }
520
         }
478
         callback.invoke(null, arg);
521
         callback.invoke(null, arg);
479
     }
522
     }
480
 
523
 
481
     static void lstat(String path, final Callback callback) {
524
     static void lstat(String path, final Callback callback) {
482
-        File src = new File(path);
525
+        path = normalizePath(path);
526
+
483
         new AsyncTask<String, Integer, Integer>() {
527
         new AsyncTask<String, Integer, Integer>() {
484
             @Override
528
             @Override
485
             protected Integer doInBackground(String ...args) {
529
             protected Integer doInBackground(String ...args) {
511
      */
555
      */
512
     static void stat(String path, Callback callback) {
556
     static void stat(String path, Callback callback) {
513
         try {
557
         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));
527
         } catch(Exception err) {
559
         } catch(Exception err) {
528
             callback.invoke(err.getLocalizedMessage());
560
             callback.invoke(err.getLocalizedMessage());
529
         }
561
         }
530
     }
562
     }
531
 
563
 
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
+     */
532
     void scanFile(String [] path, String[] mimes, final Callback callback) {
607
     void scanFile(String [] path, String[] mimes, final Callback callback) {
533
         try {
608
         try {
534
             MediaScannerConnection.scanFile(mCtx, path, mimes, new MediaScannerConnection.OnScanCompletedListener() {
609
             MediaScannerConnection.scanFile(mCtx, path, mimes, new MediaScannerConnection.OnScanCompletedListener() {
669
         this.emitter.emit("RNFetchBlobStream" + taskId, eventData);
744
         this.emitter.emit("RNFetchBlobStream" + taskId, eventData);
670
     }
745
     }
671
 
746
 
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;
676
         }
799
         }
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;
684
     }
801
     }
685
 
802
 
686
 }
803
 }

+ 12
- 1
src/fs.js 查看文件

8
 import {
8
 import {
9
   NativeModules,
9
   NativeModules,
10
   DeviceEventEmitter,
10
   DeviceEventEmitter,
11
+  Platform,
11
   NativeAppEventEmitter,
12
   NativeAppEventEmitter,
12
 } from 'react-native'
13
 } from 'react-native'
13
 import RNFetchBlobSession from './class/RNFetchBlobSession'
14
 import RNFetchBlobSession from './class/RNFetchBlobSession'
47
   }
48
   }
48
 }
49
 }
49
 
50
 
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
+
50
 function createFile(path:string, data:string, encoding: 'base64' | 'ascii' | 'utf8'):Promise {
60
 function createFile(path:string, data:string, encoding: 'base64' | 'ascii' | 'utf8'):Promise {
51
   encoding = encoding || 'utf8'
61
   encoding = encoding || 'utf8'
52
   return new Promise((resolve, reject) => {
62
   return new Promise((resolve, reject) => {
324
   stat,
334
   stat,
325
   lstat,
335
   lstat,
326
   scanFile,
336
   scanFile,
327
-  dirs
337
+  dirs,
338
+  asset
328
 }
339
 }

+ 1
- 1
src/index.js 查看文件

272
   config,
272
   config,
273
   session,
273
   session,
274
   fs,
274
   fs,
275
-  wrap,
275
+  wrap
276
 }
276
 }

+ 6
- 0
src/ios/RNFetchBlob.xcodeproj/project.pbxproj 查看文件

12
 		A158F4301D0539DB006FFD38 /* RNFetchBlobNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = A158F42F1D0539DB006FFD38 /* RNFetchBlobNetwork.m */; };
12
 		A158F4301D0539DB006FFD38 /* RNFetchBlobNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = A158F42F1D0539DB006FFD38 /* RNFetchBlobNetwork.m */; };
13
 		A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = A15C30131CD25C330074CB35 /* RNFetchBlob.m */; };
13
 		A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = A15C30131CD25C330074CB35 /* RNFetchBlob.m */; };
14
 		A166D1AA1CE0647A00273590 /* RNFetchBlob.h in Sources */ = {isa = PBXBuildFile; fileRef = A15C30111CD25C330074CB35 /* RNFetchBlob.h */; };
14
 		A166D1AA1CE0647A00273590 /* RNFetchBlob.h in Sources */ = {isa = PBXBuildFile; fileRef = A15C30111CD25C330074CB35 /* RNFetchBlob.h */; };
15
+		A1AAE2991D300E4D0051D11C /* RNFetchBlobReqBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = A1AAE2981D300E4D0051D11C /* RNFetchBlobReqBuilder.m */; };
15
 /* End PBXBuildFile section */
16
 /* End PBXBuildFile section */
16
 
17
 
17
 /* Begin PBXCopyFilesBuildPhase section */
18
 /* Begin PBXCopyFilesBuildPhase section */
36
 		A15C300E1CD25C330074CB35 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFetchBlob.a; sourceTree = BUILT_PRODUCTS_DIR; };
37
 		A15C300E1CD25C330074CB35 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFetchBlob.a; sourceTree = BUILT_PRODUCTS_DIR; };
37
 		A15C30111CD25C330074CB35 /* RNFetchBlob.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFetchBlob.h; path = RNFetchBlob/RNFetchBlob.h; sourceTree = "<group>"; };
38
 		A15C30111CD25C330074CB35 /* RNFetchBlob.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFetchBlob.h; path = RNFetchBlob/RNFetchBlob.h; sourceTree = "<group>"; };
38
 		A15C30131CD25C330074CB35 /* RNFetchBlob.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFetchBlob.m; path = RNFetchBlob/RNFetchBlob.m; sourceTree = "<group>"; };
39
 		A15C30131CD25C330074CB35 /* RNFetchBlob.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFetchBlob.m; path = RNFetchBlob/RNFetchBlob.m; sourceTree = "<group>"; };
40
+		A1AAE2971D300E3E0051D11C /* RNFetchBlobReqBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNFetchBlobReqBuilder.h; sourceTree = "<group>"; };
41
+		A1AAE2981D300E4D0051D11C /* RNFetchBlobReqBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNFetchBlobReqBuilder.m; sourceTree = "<group>"; };
39
 /* End PBXFileReference section */
42
 /* End PBXFileReference section */
40
 
43
 
41
 /* Begin PBXFrameworksBuildPhase section */
44
 /* Begin PBXFrameworksBuildPhase section */
59
 		A15C30051CD25C330074CB35 = {
62
 		A15C30051CD25C330074CB35 = {
60
 			isa = PBXGroup;
63
 			isa = PBXGroup;
61
 			children = (
64
 			children = (
65
+				A1AAE2981D300E4D0051D11C /* RNFetchBlobReqBuilder.m */,
66
+				A1AAE2971D300E3E0051D11C /* RNFetchBlobReqBuilder.h */,
62
 				A158F42F1D0539DB006FFD38 /* RNFetchBlobNetwork.m */,
67
 				A158F42F1D0539DB006FFD38 /* RNFetchBlobNetwork.m */,
63
 				A158F42E1D0539CE006FFD38 /* RNFetchBlobNetwork.h */,
68
 				A158F42E1D0539CE006FFD38 /* RNFetchBlobNetwork.h */,
64
 				A158F42C1D0535BB006FFD38 /* RNFetchBlobConst.m */,
69
 				A158F42C1D0535BB006FFD38 /* RNFetchBlobConst.m */,
140
 				A158F42D1D0535BB006FFD38 /* RNFetchBlobConst.m in Sources */,
145
 				A158F42D1D0535BB006FFD38 /* RNFetchBlobConst.m in Sources */,
141
 				A158F4271D052E49006FFD38 /* RNFetchBlobFS.m in Sources */,
146
 				A158F4271D052E49006FFD38 /* RNFetchBlobFS.m in Sources */,
142
 				A158F4301D0539DB006FFD38 /* RNFetchBlobNetwork.m in Sources */,
147
 				A158F4301D0539DB006FFD38 /* RNFetchBlobNetwork.m in Sources */,
148
+				A1AAE2991D300E4D0051D11C /* RNFetchBlobReqBuilder.m in Sources */,
143
 				A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */,
149
 				A15C30141CD25C330074CB35 /* RNFetchBlob.m in Sources */,
144
 			);
150
 			);
145
 			runOnlyForDeploymentPostprocessing = 0;
151
 			runOnlyForDeploymentPostprocessing = 0;

+ 18
- 112
src/ios/RNFetchBlob/RNFetchBlob.m 查看文件

12
 #import "RNFetchBlobFS.h"
12
 #import "RNFetchBlobFS.h"
13
 #import "RNFetchBlobNetwork.h"
13
 #import "RNFetchBlobNetwork.h"
14
 #import "RNFetchBlobConst.h"
14
 #import "RNFetchBlobConst.h"
15
+#import "RNFetchBlobReqBuilder.h"
15
 
16
 
16
 
17
 
17
 ////////////////////////////////////////
18
 ////////////////////////////////////////
61
                   form:(NSArray *)form
62
                   form:(NSArray *)form
62
                   callback:(RCTResponseSenderBlock)callback)
63
                   callback:(RCTResponseSenderBlock)callback)
63
 {
64
 {
64
-    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
65
-    // send request
66
-    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
67
-                                    initWithURL:[NSURL
68
-                                                 URLWithString: encodedUrl]];
69
     
65
     
70
-    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[ RNFetchBlobNetwork normalizeHeaders:headers]];
71
-    
72
-    
73
-    NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
74
-    NSNumber * timeStampObj = [NSNumber numberWithDouble: timeStamp];
75
-    
76
-    // generate boundary
77
-    NSString * boundary = [NSString stringWithFormat:@"RNFetchBlob%d", timeStampObj];
78
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
79
-        NSMutableData * postData = [[NSMutableData alloc] init];
80
-        // if method is POST or PUT, convert data string format
81
-        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
82
-            
83
-            // combine multipart/form-data body
84
-            for(id field in form) {
85
-                NSString * name = [field valueForKey:@"name"];
86
-                NSString * content = [field valueForKey:@"data"];
87
-                // field is a text field
88
-                if([field valueForKey:@"filename"] == nil || content == [NSNull null]) {
89
-                    [postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
90
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
91
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
92
-                    [postData appendData:[[NSString stringWithFormat:@"%@\r\n", content] dataUsingEncoding:NSUTF8StringEncoding]];
93
-                }
94
-                // field contains a file
95
-                else {
96
-                    NSMutableData * blobData;
97
-                    if(content != nil) {
98
-                        if([content hasPrefix:self.filePathPrefix]) {
99
-                            NSString * orgPath = [content substringFromIndex:[self.filePathPrefix length]];
100
-                            blobData = [[NSData alloc] initWithContentsOfFile:orgPath];
101
-                        }
102
-                        else
103
-                            blobData = [[NSData alloc] initWithBase64EncodedString:content options:0];
104
-                    }
105
-                    NSString * filename = [field valueForKey:@"filename"];
106
-                    [postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
107
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
108
-                    [postData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
109
-                    [postData appendData:blobData];
110
-                    [postData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
111
-                }
112
-                
113
-            }
114
-            
115
-            // close form data
116
-            [postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
117
-            [request setHTTPBody:postData];
118
-            // set content-length
119
-            [mheaders setValue:[NSString stringWithFormat:@"%d",[postData length]] forKey:@"Content-Length"];
120
-            [mheaders setValue:[NSString stringWithFormat:@"100-continue",[postData length]] forKey:@"Expect"];
121
-            // appaned boundary to content-type
122
-            [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
123
-            
124
-        }
125
-        
126
-        [request setHTTPMethod: method];
127
-        [request setAllHTTPHeaderFields:mheaders];
128
-        
129
-        
66
+    [RNFetchBlobReqBuilder buildMultipartRequest:options taskId:taskId method:method url:url headers:headers form:form onComplete:^(NSURLRequest *req) {
130
         // send HTTP request
67
         // send HTTP request
131
         RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
68
         RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
132
-        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request callback:callback];
69
+        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:req callback:callback];
133
         utils = nil;
70
         utils = nil;
134
-    });
71
+    }];
72
+    
135
 }
73
 }
136
 
74
 
137
 // Fetch blob data request
75
 // Fetch blob data request
142
                   headers:(NSDictionary *)headers
80
                   headers:(NSDictionary *)headers
143
                   body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
81
                   body:(NSString *)body callback:(RCTResponseSenderBlock)callback)
144
 {
82
 {
145
-    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
146
-    // send request
147
-    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
148
-                                    initWithURL:[NSURL
149
-                                                 URLWithString: encodedUrl]];
150
-    
151
-    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[RNFetchBlobNetwork normalizeHeaders:headers]];
152
-    // move heavy task to another thread
153
-    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
154
-        NSMutableData * blobData;
155
-        // if method is POST or PUT, convert data string format
156
-        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
157
-            // generate octet-stream body
158
-            if(body != nil) {
159
-                
160
-                // when body is a string contains file path prefix, try load file from the path
161
-                if([body hasPrefix:self.filePathPrefix]) {
162
-                    NSString * orgPath = [body substringFromIndex:[self.filePathPrefix length]];
163
-                    [request setHTTPBodyStream: [NSInputStream inputStreamWithFileAtPath:orgPath ]];
164
-                }
165
-                // otherwise convert it as BASE64 data string
166
-                else {
167
-                    blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
168
-                    [request setHTTPBody:blobData];
169
-                }
170
-                
171
-                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
172
-                
173
-            }
174
-        }
175
-        
176
-        [request setHTTPMethod: method];
177
-        [request setAllHTTPHeaderFields:mheaders];
178
-        
83
+    [RNFetchBlobReqBuilder buildOctetRequest:options taskId:taskId method:method url:url headers:headers body:body onComplete:^(NSURLRequest *req) {
179
         // send HTTP request
84
         // send HTTP request
180
         RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
85
         RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init];
181
-        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:request callback:callback];
86
+        [utils sendRequest:options bridge:self.bridge taskId:taskId withRequest:req callback:callback];
182
         utils = nil;
87
         utils = nil;
183
-    });
88
+    }];
89
+    
184
 }
90
 }
185
 
91
 
186
 RCT_EXPORT_METHOD(createFile:(NSString *)path data:(NSString *)data encoding:(NSString *)encoding callback:(RCTResponseSenderBlock)callback) {
92
 RCT_EXPORT_METHOD(createFile:(NSString *)path data:(NSString *)data encoding:(NSString *)encoding callback:(RCTResponseSenderBlock)callback) {
332
     BOOL exist = nil;
238
     BOOL exist = nil;
333
     BOOL isDir = nil;
239
     BOOL isDir = nil;
334
     NSError * error = nil;
240
     NSError * error = nil;
241
+    
242
+    path = [RNFetchBlobFS getPathOfAsset:path];
243
+    
335
     exist = [fm fileExistsAtPath:path isDirectory:&isDir];
244
     exist = [fm fileExistsAtPath:path isDirectory:&isDir];
336
     if(exist == NO) {
245
     if(exist == NO) {
337
         callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not exist", path]]);
246
         callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not exist", path]]);
350
     NSFileManager* fm = [NSFileManager defaultManager];
259
     NSFileManager* fm = [NSFileManager defaultManager];
351
     BOOL exist = nil;
260
     BOOL exist = nil;
352
     BOOL isDir = nil;
261
     BOOL isDir = nil;
262
+    
263
+    path = [RNFetchBlobFS getPathOfAsset:path];
264
+    
353
     exist = [fm fileExistsAtPath:path isDirectory:&isDir];
265
     exist = [fm fileExistsAtPath:path isDirectory:&isDir];
354
     if(exist == NO) {
266
     if(exist == NO) {
355
         callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not exist", path]]);
267
         callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not exist", path]]);
378
 
290
 
379
 RCT_EXPORT_METHOD(cp:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback) {
291
 RCT_EXPORT_METHOD(cp:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback) {
380
     NSError * error = nil;
292
     NSError * error = nil;
293
+    path = [RNFetchBlobFS getPathOfAsset:path];
381
     BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
294
     BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
382
     
295
     
383
     if(error == nil)
296
     if(error == nil)
410
 
323
 
411
 RCT_EXPORT_METHOD(readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
324
 RCT_EXPORT_METHOD(readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
412
     
325
     
413
-    [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject];
326
+    [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject onComplete:nil];
414
 })
327
 })
415
 
328
 
416
 RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize) {
329
 RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize) {
423
             bufferSize = 4096;
336
             bufferSize = 4096;
424
     }
337
     }
425
     // read asset stream
338
     // read asset stream
426
-    if([path hasPrefix:@"assets-library://"])
427
-    {
428
-        
429
-    }
430
-    else
431
-    {
432
-        [fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
433
-    }
339
+    [fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
434
 }
340
 }
435
 
341
 
436
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {
342
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {

+ 3
- 0
src/ios/RNFetchBlobConst.h 查看文件

16
 extern NSString *const MSG_EVENT_LOG;
16
 extern NSString *const MSG_EVENT_LOG;
17
 extern NSString *const MSG_EVENT_WARN;
17
 extern NSString *const MSG_EVENT_WARN;
18
 extern NSString *const MSG_EVENT_ERROR;
18
 extern NSString *const MSG_EVENT_ERROR;
19
+
19
 extern NSString *const FILE_PREFIX;
20
 extern NSString *const FILE_PREFIX;
21
+extern NSString *const ASSET_PREFIX;
22
+extern NSString *const AL_PREFIX;
20
 
23
 
21
 // config
24
 // config
22
 extern NSString *const CONFIG_USE_TEMP;
25
 extern NSString *const CONFIG_USE_TEMP;

+ 4
- 0
src/ios/RNFetchBlobConst.m 查看文件

8
 #import "RNFetchBlobConst.h"
8
 #import "RNFetchBlobConst.h"
9
 
9
 
10
 extern NSString *const FILE_PREFIX = @"RNFetchBlob-file://";
10
 extern NSString *const FILE_PREFIX = @"RNFetchBlob-file://";
11
+extern NSString *const ASSET_PREFIX = @"bundle-assets://";
12
+extern NSString *const AL_PREFIX = @"assets-library://";
13
+
14
+
11
 
15
 
12
 // fetch configs
16
 // fetch configs
13
 extern NSString *const CONFIG_USE_TEMP = @"fileCache";
17
 extern NSString *const CONFIG_USE_TEMP = @"fileCache";

+ 4
- 2
src/ios/RNFetchBlobFS.h 查看文件

11
 
11
 
12
 #import <Foundation/Foundation.h>
12
 #import <Foundation/Foundation.h>
13
 #import "RCTBridgeModule.h"
13
 #import "RCTBridgeModule.h"
14
+@import AssetsLibrary;
14
 
15
 
15
 @interface RNFetchBlobFS : NSObject <NSStreamDelegate>  {
16
 @interface RNFetchBlobFS : NSObject <NSStreamDelegate>  {
16
     NSOutputStream * outStream;
17
     NSOutputStream * outStream;
42
 + (NSString *) getCacheDir;
43
 + (NSString *) getCacheDir;
43
 + (NSString *) getDocumentDir;
44
 + (NSString *) getDocumentDir;
44
 + (NSString *) getTempPath:(NSString*)taskId withExtension:(NSString *)ext;
45
 + (NSString *) getTempPath:(NSString*)taskId withExtension:(NSString *)ext;
46
++ (NSString *) getPathOfAsset:(NSString *)assetURI;
47
++ (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, ALAssetRepresentation *asset)) onComplete;
45
 
48
 
46
 // fs methods
49
 // fs methods
47
 + (RNFetchBlobFS *) getFileStreams;
50
 + (RNFetchBlobFS *) getFileStreams;
50
 + (BOOL) exists:(NSString *) path;
53
 + (BOOL) exists:(NSString *) path;
51
 + (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
54
 + (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
52
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
55
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
53
-+ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
56
++ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject onComplete:(void (^)(NSData * content))onComplete;
54
 + (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock;
57
 + (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock;
55
-+ (NSString *) getPathOfAsset:(NSString *)assetURI;
56
 
58
 
57
 // constructor
59
 // constructor
58
 - (id) init;
60
 - (id) init;

+ 72
- 85
src/ios/RNFetchBlobFS.m 查看文件

16
 #import "RNFetchBlobConst.h"
16
 #import "RNFetchBlobConst.h"
17
 @import AssetsLibrary;
17
 @import AssetsLibrary;
18
 
18
 
19
+
19
 NSMutableDictionary *fileStreams = nil;
20
 NSMutableDictionary *fileStreams = nil;
20
 
21
 
21
 ////////////////////////////////////////
22
 ////////////////////////////////////////
53
 +(NSString *) getPathOfAsset:(NSString *)assetURI
54
 +(NSString *) getPathOfAsset:(NSString *)assetURI
54
 {
55
 {
55
     // get file path of an app asset
56
     // get file path of an app asset
56
-    if([assetURI hasPrefix:@"bundle-assets://"])
57
+    if([assetURI hasPrefix:ASSET_PREFIX])
57
     {
58
     {
58
-        assetURI = [assetURI stringByReplacingOccurrencesOfString:@"bundle-assets://" withString:@""];
59
+        assetURI = [assetURI stringByReplacingOccurrencesOfString:ASSET_PREFIX withString:@""];
59
         assetURI = [[NSBundle mainBundle] pathForResource: [assetURI stringByDeletingPathExtension]
60
         assetURI = [[NSBundle mainBundle] pathForResource: [assetURI stringByDeletingPathExtension]
60
                                                ofType: [assetURI pathExtension]];
61
                                                ofType: [assetURI pathExtension]];
61
     }
62
     }
97
     return tempPath;
98
     return tempPath;
98
 }
99
 }
99
 
100
 
100
-- (void) startAssetReadStream:(NSData *)assetUrl
101
+- (void) startAssetReadStream:(NSString *)assetUrl
101
 {
102
 {
102
     ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
103
     ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
103
     {
104
     {
184
     }
185
     }
185
 }
186
 }
186
 
187
 
187
-// read system asset file
188
-+ (void) readAssetFile:(NSData *)assetUrl completionBlock:(void(^)(NSData * content))completionBlock failBlock:(void(^)(NSError * err))failBlock
189
-{
190
-    
191
-    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
192
-    {
193
-        ALAssetRepresentation *rep = [myasset defaultRepresentation];
194
-        Byte *buffer = (Byte*)malloc(rep.size);
195
-        NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
196
-        NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
197
-        completionBlock(data);
198
-    };
199
-    
200
-    ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *error)
201
-    {
202
-        failBlock(error);
203
-    };
204
-    
205
-    if(assetUrl && [assetUrl length])
206
-    {
207
-        NSURL *asseturl = [NSURL URLWithString:assetUrl];
208
-        ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
209
-        [assetslibrary assetForURL:asseturl
210
-                       resultBlock:resultblock
211
-                      failureBlock:failureblock];
212
-    }
213
-}
214
-
215
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
188
 + (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
216
     @try {
189
     @try {
217
         NSFileManager * fm = [NSFileManager defaultManager];
190
         NSFileManager * fm = [NSFileManager defaultManager];
300
     }
273
     }
301
 }
274
 }
302
 
275
 
303
-+ (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
276
++ (void) readFile:(NSString *)path encoding:(NSString *)encoding
277
+         resolver:(RCTPromiseResolveBlock)resolve
278
+         rejecter:(RCTPromiseRejectBlock)reject
279
+       onComplete:(void (^)(NSData * content))onComplete
280
+{
304
     @try
281
     @try
305
     {
282
     {
306
-        // before start reading file, we have to check if the `path` contains any special prefix
307
-        // if the `path` begins with the following prefix then it will need special handling.
308
-        //      "assets-library://" this kind of path usually comes from camera roll, should use it's own readFile implementation
309
-        //      "bundle-assets://" this means an asset inside app bundle, usually we only have to convert it into normal file path
310
-        if([path hasPrefix:@"assets-library://"])
311
-        {
312
-            [[self class] readAssetFile:path completionBlock:^(NSData * content)
283
+        [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
284
+            NSData * fileContent;
285
+            NSError * err;
286
+            if(asset != nil)
287
+            {
288
+                Byte * buffer = malloc(asset.size);
289
+                [asset getBytes:buffer fromOffset:0 length:asset.size error:&err];
290
+                if(err != nil)
291
+                {
292
+                    reject(@"RNFetchBlobFS readFile error", @"failed to read asset", [err localizedDescription]);
293
+                    return;
294
+                }
295
+                fileContent = [NSData dataWithBytes:buffer length:asset.size];
296
+                if(onComplete != nil)
297
+                    onComplete(fileContent);
298
+                free(buffer);
299
+            }
300
+            else
313
             {
301
             {
314
-                if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
315
-                    resolve([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]);
302
+                BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path];
303
+                if(!exists) {
304
+                    reject(@"RNFetchBlobFS readFile error", @"file not exists", path);
305
+                    return;
316
                 }
306
                 }
317
-                else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
318
-                    resolve([content base64EncodedStringWithOptions:0]);
307
+                fileContent = [NSData dataWithContentsOfFile:path];
308
+            }
309
+            
310
+            if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
311
+                if(resolve != nil)
312
+                    resolve([[NSString alloc] initWithData:fileContent encoding:NSUTF8StringEncoding]);
313
+            }
314
+            else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
315
+                if(resolve != nil)
316
+                    resolve([fileContent base64EncodedStringWithOptions:0]);
317
+            }
318
+            else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
319
+                NSMutableArray * resultArray = [NSMutableArray array];
320
+                char * bytes = [fileContent bytes];
321
+                for(int i=0;i<[fileContent length];i++) {
322
+                    [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
319
                 }
323
                 }
320
-                else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
321
-                    NSMutableArray * resultArray = [NSMutableArray array];
322
-                    char * bytes = [content bytes];
323
-                    for(int i=0;i<[content length];i++) {
324
-                        [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
325
-                    }
324
+                if(resolve != nil)
326
                     resolve(resultArray);
325
                     resolve(resultArray);
327
-                }
328
-            } failBlock:^(NSError *err) {
329
-                @throw @"RNFetchBlobFS readFile error", @"failed to read asset", path;
330
-            }];
331
-            return ;
332
-        }
333
-        
334
-        // normalize the file path
335
-        path = [[self class]getPathOfAsset:path];
336
-        
337
-        NSFileManager * fm = [NSFileManager defaultManager];
338
-        NSError *err = nil;
339
-        BOOL exists = [fm fileExistsAtPath:path];
340
-        if(!exists) {
341
-            @throw @"RNFetchBlobFS readFile error", @"file not exists", path;
342
-            return;
343
-        }
344
-        if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
345
-            NSString * utf8Result = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
346
-            resolve(utf8Result);
347
-        }
348
-        else if ([[encoding lowercaseString] isEqualToString:@"base64"]) {
349
-            NSData * fileData = [NSData dataWithContentsOfFile:path];
350
-            resolve([fileData base64EncodedStringWithOptions:0]);
351
-        }
352
-        else if ([[encoding lowercaseString] isEqualToString:@"ascii"]) {
353
-            NSData * resultData = [NSData dataWithContentsOfFile:path];
354
-            NSMutableArray * resultArray = [NSMutableArray array];
355
-            char * bytes = [resultData bytes];
356
-            for(int i=0;i<[resultData length];i++) {
357
-                [resultArray addObject:[NSNumber numberWithChar:bytes[i]]];
358
             }
326
             }
359
-            resolve(resultArray);
360
-        }
361
-
327
+        }];
362
     }
328
     }
363
     @catch(NSException * e)
329
     @catch(NSException * e)
364
     {
330
     {
331
+        if(reject != nil)
365
         reject(@"RNFetchBlobFS readFile error", @"error", [e description]);
332
         reject(@"RNFetchBlobFS readFile error", @"error", [e description]);
366
     }
333
     }
367
 }
334
 }
485
     self.path = path;
452
     self.path = path;
486
     self.bufferSize = bufferSize;
453
     self.bufferSize = bufferSize;
487
     
454
     
488
-    if([path hasPrefix:@"assets-library://"])
455
+    if([path hasPrefix:AL_PREFIX])
489
     {
456
     {
490
-     
457
+        [self startAssetReadStream:path];
491
         return;
458
         return;
492
     }
459
     }
493
     
460
     
630
 
597
 
631
 }
598
 }
632
 
599
 
600
++ (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, ALAssetRepresentation *asset)) onComplete
601
+{
602
+    if([uri hasPrefix:AL_PREFIX])
603
+    {
604
+        NSURL *asseturl = [NSURL URLWithString:uri];
605
+        ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
606
+        [assetslibrary assetForURL:asseturl
607
+                       resultBlock:^(ALAsset *asset) {
608
+                           onComplete(nil, [asset defaultRepresentation]);
609
+                       }
610
+                      failureBlock:^(NSError *error) {
611
+                          onComplete(nil, nil);
612
+                      }];
613
+    }
614
+    else
615
+    {
616
+        onComplete([[self class] getPathOfAsset:uri], nil);
617
+    }
618
+}
619
+
633
 @end
620
 @end

+ 1
- 0
src/ios/RNFetchBlobNetwork.h 查看文件

11
 
11
 
12
 #import <Foundation/Foundation.h>
12
 #import <Foundation/Foundation.h>
13
 #import "RCTBridgeModule.h"
13
 #import "RCTBridgeModule.h"
14
+#import "RNFetchBlobFS.h"
14
 
15
 
15
 typedef void(^CompletionHander)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error);
16
 typedef void(^CompletionHander)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error);
16
 typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error);
17
 typedef void(^DataTaskCompletionHander) (NSData * _Nullable resp, NSURLResponse * _Nullable response, NSError * _Nullable error);

+ 34
- 0
src/ios/RNFetchBlobReqBuilder.h 查看文件

1
+//
2
+//  RNFetchBlobReqBuilder.h
3
+//  RNFetchBlob
4
+//
5
+//  Created by Ben Hsieh on 2016/7/9.
6
+//  Copyright © 2016年 wkh237. All rights reserved.
7
+//
8
+
9
+#ifndef RNFetchBlobReqBuilder_h
10
+#define RNFetchBlobReqBuilder_h
11
+
12
+#import <Foundation/Foundation.h>
13
+
14
+@interface RNFetchBlobReqBuilder : NSObject;
15
+
16
++(void) buildMultipartRequest:(NSDictionary *)options
17
+                       taskId:(NSString *)taskId
18
+                       method:(NSString *)method
19
+                          url:(NSString *)url
20
+                      headers:(NSDictionary *)headers
21
+                         form:(NSArray *)form
22
+                   onComplete:(void(^)(NSURLRequest * req))onComplete;
23
+
24
++(void) buildOctetRequest:(NSDictionary *)options
25
+                   taskId:(NSString *)taskId
26
+                   method:(NSString *)method
27
+                      url:(NSString *)url
28
+                  headers:(NSDictionary *)headers
29
+                     body:(NSString *)body
30
+               onComplete:(void(^)(NSURLRequest * req))onComplete;
31
+
32
+@end
33
+
34
+#endif /* RNFetchBlobReqBuilder_h */

+ 195
- 0
src/ios/RNFetchBlobReqBuilder.m 查看文件

1
+//
2
+//  RNFetchBlobReqBuilder.m
3
+//  RNFetchBlob
4
+//
5
+//  Created by Ben Hsieh on 2016/7/9.
6
+//  Copyright © 2016年 wkh237. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+#import "RNFetchBlobReqBuilder.h"
11
+#import "RNFetchBlobNetwork.h"
12
+#import "RNFetchBlobConst.h"
13
+#import "RNFetchBlobFS.h"
14
+
15
+@interface RNFetchBlobReqBuilder()
16
+{
17
+    
18
+}
19
+@end
20
+
21
+@implementation RNFetchBlobReqBuilder
22
+
23
+
24
+// Fetch blob data request
25
++(void) buildMultipartRequest:(NSDictionary *)options
26
+                       taskId:(NSString *)taskId
27
+                       method:(NSString *)method
28
+                          url:(NSString *)url
29
+                      headers:(NSDictionary *)headers
30
+                         form:(NSArray *)form
31
+                   onComplete:(void(^)(NSURLRequest * req))onComplete
32
+{
33
+    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
34
+    // send request
35
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString: encodedUrl]];
36
+    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[RNFetchBlobNetwork normalizeHeaders:headers]];
37
+    NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
38
+    NSNumber * timeStampObj = [NSNumber numberWithDouble: timeStamp];
39
+    
40
+    // generate boundary
41
+    NSString * boundary = [NSString stringWithFormat:@"RNFetchBlob%d", timeStampObj];
42
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
43
+        NSMutableData * postData = [[NSMutableData alloc] init];
44
+        // combine multipart/form-data body
45
+        [[self class] buildFormBody:form boundary:boundary onComplete:^(NSData *formData) {
46
+            if(formData != nil) {
47
+                [postData appendData:formData];
48
+                // close form data
49
+                [postData appendData: [[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
50
+                [request setHTTPBody:postData];
51
+            }
52
+            // set content-length
53
+            [mheaders setValue:[NSString stringWithFormat:@"%d",[postData length]] forKey:@"Content-Length"];
54
+            [mheaders setValue:[NSString stringWithFormat:@"100-continue",[postData length]] forKey:@"Expect"];
55
+            // appaned boundary to content-type
56
+            [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
57
+            [request setHTTPMethod: method];
58
+            [request setAllHTTPHeaderFields:mheaders];
59
+            onComplete(request);
60
+        }];
61
+        
62
+    });
63
+}
64
+
65
+// Fetch blob data request
66
++(void) buildOctetRequest:(NSDictionary *)options
67
+                   taskId:(NSString *)taskId
68
+                   method:(NSString *)method
69
+                      url:(NSString *)url
70
+                  headers:(NSDictionary *)headers
71
+                     body:(NSString *)body
72
+               onComplete:(void(^)(NSURLRequest * req))onComplete
73
+{
74
+    NSString * encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
75
+    // send request
76
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
77
+                                    initWithURL:[NSURL
78
+                                                 URLWithString: encodedUrl]];
79
+    
80
+    NSMutableDictionary *mheaders = [[NSMutableDictionary alloc] initWithDictionary:[RNFetchBlobNetwork normalizeHeaders:headers]];
81
+    // move heavy task to another thread
82
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
83
+        NSMutableData * blobData;
84
+        // if method is POST or PUT, convert data string format
85
+        if([[method lowercaseString] isEqualToString:@"post"] || [[method lowercaseString] isEqualToString:@"put"]) {
86
+            // generate octet-stream body
87
+            if(body != nil) {
88
+                
89
+                // when body is a string contains file path prefix, try load file from the path
90
+                if([body hasPrefix:FILE_PREFIX]) {
91
+                    NSString * orgPath = [body substringFromIndex:[FILE_PREFIX length]];
92
+                    orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
93
+                    if([orgPath hasPrefix:AL_PREFIX])
94
+                    {
95
+                        [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
96
+                            [request setHTTPBody:content];
97
+                            [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
98
+                            [request setHTTPMethod: method];
99
+                            [request setAllHTTPHeaderFields:mheaders];
100
+                            onComplete(request);
101
+                        }];
102
+                        return;
103
+                    }
104
+                    [request setHTTPBodyStream: [NSInputStream inputStreamWithFileAtPath:orgPath ]];
105
+                }
106
+                // otherwise convert it as BASE64 data string
107
+                else {
108
+                    blobData = [[NSData alloc] initWithBase64EncodedString:body options:0];
109
+                    [request setHTTPBody:blobData];
110
+                }
111
+                
112
+                [mheaders setValue:@"application/octet-stream" forKey:@"content-type"];
113
+                
114
+            }
115
+        }
116
+        
117
+        [request setHTTPMethod: method];
118
+        [request setAllHTTPHeaderFields:mheaders];
119
+        
120
+        onComplete(request);
121
+    });
122
+}
123
+
124
++(void) buildFormBody:(NSArray *)form boundary:(NSString *)boundary onComplete:(void(^)(NSData * formData))onComplete
125
+{
126
+    NSMutableData * formData = [[NSMutableData alloc] init];
127
+    if(form == nil)
128
+        onComplete(nil);
129
+    else
130
+    {
131
+        __block int i = 0;
132
+        __block int count = [form count];
133
+        void __block (^getFieldData)(id field) = ^(id field)
134
+        {
135
+            NSString * name = [field valueForKey:@"name"];
136
+            NSString * content = [field valueForKey:@"data"];
137
+            // field is a text field
138
+            if([field valueForKey:@"filename"] == nil || content == [NSNull null]) {
139
+                [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
140
+                [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", name] dataUsingEncoding:NSUTF8StringEncoding]];
141
+                [formData appendData:[[NSString stringWithFormat:@"Content-Type: text/plain\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
142
+                [formData appendData:[[NSString stringWithFormat:@"%@\r\n", content] dataUsingEncoding:NSUTF8StringEncoding]];
143
+            }
144
+            // field contains a file
145
+            else {
146
+                NSMutableData * blobData;
147
+                if(content != nil)
148
+                {
149
+                    // append data from file asynchronously
150
+                    if([content hasPrefix:FILE_PREFIX])
151
+                    {
152
+                        NSString * orgPath = [content substringFromIndex:[FILE_PREFIX length]];
153
+                        orgPath = [RNFetchBlobFS getPathOfAsset:orgPath];
154
+                        [RNFetchBlobFS readFile:orgPath encoding:@"utf8" resolver:nil rejecter:nil onComplete:^(NSData *content) {
155
+                            NSString * filename = [field valueForKey:@"filename"];
156
+                            [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
157
+                            [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
158
+                            [formData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
159
+                            [formData appendData:content];
160
+                            [formData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
161
+                            i++;
162
+                            if(i < count)
163
+                            {
164
+                                getFieldData([form objectAtIndex:i]);
165
+                            }
166
+                            else
167
+                                onComplete(formData);
168
+                        }];
169
+                        return ;
170
+                    }
171
+                    else
172
+                        blobData = [[NSData alloc] initWithBase64EncodedString:content options:0];
173
+                }
174
+                NSString * filename = [field valueForKey:@"filename"];
175
+                [formData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
176
+                [formData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename] dataUsingEncoding:NSUTF8StringEncoding]];
177
+                [formData appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
178
+                [formData appendData:blobData];
179
+                [formData appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
180
+            }
181
+            i++;
182
+            if(i < count)
183
+            {
184
+                getFieldData([form objectAtIndex:i]);
185
+            }
186
+            else
187
+                onComplete(formData);
188
+            
189
+        };
190
+        getFieldData([form objectAtIndex:i]);
191
+    }
192
+}
193
+
194
+
195
+@end

+ 113
- 32
test/test-0.6.2.js 查看文件

18
 const describe = RNTest.config({
18
 const describe = RNTest.config({
19
   group : '0.6.2',
19
   group : '0.6.2',
20
   run : true,
20
   run : true,
21
-  expand : true,
21
+  expand : false,
22
   timeout : 12000,
22
   timeout : 12000,
23
 })
23
 })
24
-const { TEST_SERVER_URL_SSL, FILENAME, DROPBOX_TOKEN, styles } = prop()
24
+const { TEST_SERVER_URL, TEST_SERVER_URL_SSL, DROPBOX_TOKEN, styles } = prop()
25
 const  dirs = RNFetchBlob.fs.dirs
25
 const  dirs = RNFetchBlob.fs.dirs
26
 
26
 
27
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
27
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
28
+let photo = null
28
 
29
 
29
-
30
-describe('access assets from camera roll', (report, done) => {
31
-  let photo = null
30
+describe('upload asset from camera roll', (report, done) => {
31
+  let imgName = `image-from-camera-roll-${Platform.OS}.jpg`
32
   CameraRoll.getPhotos({first : 10})
32
   CameraRoll.getPhotos({first : 10})
33
     .then((resp) => {
33
     .then((resp) => {
34
-      photo = resp.edges[0].node.image.uri
35
-      report(<Info key="items">
36
-        <Text>{photo}</Text>
37
-      </Info>)
38
-      return fs.readFile(photo, 'base64')
34
+      let url = resp.edges[0].node.image.uri
35
+      photo = url
36
+      return RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
37
+        Authorization : `Bearer ${DROPBOX_TOKEN}`,
38
+        'Dropbox-API-Arg': `{\"path\": \"/rn-upload/${imgName}\",\"mode\": \"add\",\"autorename\": false,\"mute\": false}`,
39
+        'Content-Type' : 'application/octet-stream',
40
+      }, RNFetchBlob.wrap(url))
41
+    })
42
+    .then((resp) => {
43
+      resp = resp.json()
44
+      report(
45
+        <Assert key="confirm the file has been uploaded" expect={imgName} actual={resp.name}/>
46
+      )
47
+      done()
48
+    })
49
+})
50
+
51
+describe('Upload multipart data with file from CameraRoll', (report, done) => {
52
+    let filename = 'test-from-storage-img-'+Date.now()+'.png'
53
+    RNFetchBlob.fetch('POST', `${TEST_SERVER_URL}/upload-form`, {
54
+        'Content-Type' : 'multipart/form-data',
55
+      }, [
56
+        { name : 'test-img', filename : filename, data: RNFetchBlob.wrap(photo)},
57
+        { name : 'test-text', filename : 'test-text.txt', data: RNFetchBlob.base64.encode('hello.txt')},
58
+        { name : 'field1', data : 'hello !!'},
59
+        { name : 'field2', data : 'hello2 !!'}
60
+      ])
61
+    .then((resp) => {
62
+      resp = resp.json()
63
+      report(
64
+        <Assert key="check posted form data #1" expect="hello !!" actual={resp.fields.field1}/>,
65
+        <Assert key="check posted form data #2" expect="hello2 !!" actual={resp.fields.field2}/>,
66
+      )
67
+      return RNFetchBlob.fetch('GET', `${TEST_SERVER_URL}/public/${filename}`)
39
     })
68
     })
40
-    .then((data) => {
41
-      report(<Info key="asset image">
69
+    .then((resp) => {
70
+      report(<Info key="uploaded image">
42
         <Image
71
         <Image
43
           style={styles.image}
72
           style={styles.image}
44
-          source={{uri: `data:image/png;base64, ${data}`}}/>
73
+          source={{ uri : 'data:image/png;base64, '+ resp.base64()}}/>
45
       </Info>)
74
       </Info>)
46
       done()
75
       done()
47
     })
76
     })
48
 })
77
 })
49
 
78
 
50
-describe('read asset in app bundle',(report, done) => {
51
-  let target = 'bundle-assets://test-asset2.png'
52
-  fs.readFile(target, 'base64')
53
-  .then((data) => {
54
-    report(<Info key="asset image">
55
-      <Image
56
-        style={styles.image}
57
-        source={{uri: `data:image/png;base64, ${data}`}}/>
58
-    </Info>)
59
-    return fs.readFile('bundle-assets://test-asset1.json', 'utf8')
60
-  })
61
-  .then((resp) => {
62
-    report(
63
-      <Assert key="asset content verify"
64
-        expect="asset#1"
65
-        actual={JSON.parse(resp).secret}/>)
66
-      done()
67
-  })
68
-})
79
+//
80
+// describe('access assets from camera roll', (report, done) => {
81
+//   let photo = null
82
+//   CameraRoll.getPhotos({first : 10})
83
+//     .then((resp) => {
84
+//       photo = resp.edges[0].node.image.uri
85
+//       report(<Info key="items">
86
+//         <Text>{photo}</Text>
87
+//       </Info>)
88
+//       return fs.readFile(photo, 'base64')
89
+//     })
90
+//     .then((data) => {
91
+//       report(<Info key="asset image">
92
+//         <Image
93
+//           style={styles.image}
94
+//           source={{uri: `data:image/png;base64, ${data}`}}/>
95
+//       </Info>)
96
+//       done()
97
+//     })
98
+// })
99
+//
100
+// describe('read asset in app bundle',(report, done) => {
101
+//   let target = fs.asset('test-asset2.png')
102
+//   fs.readFile(target, 'base64')
103
+//   .then((data) => {
104
+//     report(<Info key="asset image">
105
+//       <Image
106
+//         style={styles.image}
107
+//         source={{uri: `data:image/png;base64, ${data}`}}/>
108
+//     </Info>)
109
+//     return fs.readFile(fs.asset('test-asset1.json'), 'utf8')
110
+//   })
111
+//   .then((resp) => {
112
+//     report(
113
+//       <Assert key="asset content verify"
114
+//         expect="asset#1"
115
+//         actual={JSON.parse(resp).secret}/>)
116
+//       done()
117
+//   })
118
+// })
119
+//
120
+// describe('stat assets in app', (report, done) => {
121
+//   fs.stat(fs.asset('test-asset2.png'))
122
+//     .then((data) => {
123
+//       report(<Info key="list of assets">
124
+//         <Text>{JSON.stringify(data)}</Text>
125
+//       </Info>)
126
+//       done()
127
+//     })
128
+// })
129
+//
130
+// describe('copy asset', (report, done) => {
131
+//   let dest = `${dirs.DocumentDir}/test-asset-1-${Date.now()}.json`
132
+//   fs.cp(fs.asset('test-asset1.json'), dest)
133
+//     .then(() => fs.readFile(dest, 'utf8'))
134
+//     .then((data) => {
135
+//       report(<Assert key="asset copied correctly"
136
+//         expect={'asset#1'}
137
+//         actual={JSON.parse(data).secret}/>)
138
+//       return fs.stat(fs.asset('test-asset1.json'))
139
+//     })
140
+//     .then((stat) => {
141
+//       report(<Assert key="file size check"
142
+//         expect={27}
143
+//         actual={Math.floor(stat.size)}/>,
144
+//       <Info key="dest file info">
145
+//         <Text>{JSON.stringify(stat)}</Text>
146
+//       </Info>)
147
+//       done()
148
+//     })
149
+// })

+ 8
- 8
test/test-init.js 查看文件

18
 // test environment variables
18
 // test environment variables
19
 
19
 
20
 prop('FILENAME', `${Platform.OS}-0.7.0-${Date.now()}.png`)
20
 prop('FILENAME', `${Platform.OS}-0.7.0-${Date.now()}.png`)
21
-prop('TEST_SERVER_URL', 'http://192.168.16.70:8123')
22
-prop('TEST_SERVER_URL_SSL', 'https://192.168.16.70:8124')
21
+prop('TEST_SERVER_URL', 'http://192.168.0.11:8123')
22
+prop('TEST_SERVER_URL_SSL', 'https://192.168.0.11:8124')
23
 prop('DROPBOX_TOKEN', 'fsXcpmKPrHgAAAAAAAAAoXZhcXYWdgLpQMan6Tb_bzJ237DXhgQSev12hA-gUXt4')
23
 prop('DROPBOX_TOKEN', 'fsXcpmKPrHgAAAAAAAAAoXZhcXYWdgLpQMan6Tb_bzJ237DXhgQSev12hA-gUXt4')
24
 prop('styles', {
24
 prop('styles', {
25
   image : {
25
   image : {
51
     })
51
     })
52
 })
52
 })
53
 //
53
 //
54
-// require('./test-0.1.x-0.4.x')
55
-// require('./test-0.5.1')
56
-// require('./test-0.5.2')
57
-// require('./test-0.6.0')
54
+require('./test-0.1.x-0.4.x')
55
+require('./test-0.5.1')
56
+require('./test-0.5.2')
57
+require('./test-0.6.0')
58
 require('./test-0.6.2')
58
 require('./test-0.6.2')
59
-// require('./test-fs')
60
-// require('./test-android')
59
+require('./test-fs')
60
+require('./test-android')