Browse Source

Merge branch 'master' of https://github.com/joltup/rn-fetch-blob into hash-fix

# Conflicts:
#	android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java
Ankit Makwana 5 years ago
parent
commit
fc7ae6cac8

+ 3
- 3
README.md View File

20
 * [Installation](#user-content-installation)
20
 * [Installation](#user-content-installation)
21
 * [HTTP Data Transfer](#user-content-http-data-transfer)
21
 * [HTTP Data Transfer](#user-content-http-data-transfer)
22
  * [Regular Request](#user-content-regular-request)
22
  * [Regular Request](#user-content-regular-request)
23
- * [Download file](#user-content-download-example--fetch-files-that-needs-authorization-token)
23
+ * [Download file](#download-example-fetch-files-that-need-authorization-token)
24
  * [Upload file](#user-content-upload-example--dropbox-files-upload-api)
24
  * [Upload file](#user-content-upload-example--dropbox-files-upload-api)
25
  * [Multipart/form upload](#user-content-multipartform-data-example--post-form-data-with-file-and-data)
25
  * [Multipart/form upload](#user-content-multipartform-data-example--post-form-data-with-file-and-data)
26
  * [Upload/Download progress](#user-content-uploaddownload-progress)
26
  * [Upload/Download progress](#user-content-uploaddownload-progress)
79
 For 0.29.2+ projects, simply link native packages via the following command (note: rnpm has been merged into react-native)
79
 For 0.29.2+ projects, simply link native packages via the following command (note: rnpm has been merged into react-native)
80
 
80
 
81
 ```
81
 ```
82
-react-native link
82
+react-native link rn-fetch-blob
83
 ```
83
 ```
84
 
84
 
85
 As for projects < 0.29 you need `rnpm` to link native packages
85
 As for projects < 0.29 you need `rnpm` to link native packages
91
 Optionally, use the following command to add Android permissions to `AndroidManifest.xml` automatically
91
 Optionally, use the following command to add Android permissions to `AndroidManifest.xml` automatically
92
 
92
 
93
 ```sh
93
 ```sh
94
-RNFB_ANDROID_PERMISSIONS=true react-native link
94
+RNFB_ANDROID_PERMISSIONS=true react-native link rn-fetch-blob
95
 ```
95
 ```
96
 
96
 
97
 pre 0.29 projects
97
 pre 0.29 projects

+ 5
- 1
android/src/main/java/com/RNFetchBlob/RNFetchBlob.java View File

118
 
118
 
119
                 // Set flag to give temporary permission to external app to use FileProvider
119
                 // Set flag to give temporary permission to external app to use FileProvider
120
                 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
120
                 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
121
+                 // All the activity to be opened outside of an activity
122
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
121
 
123
 
124
+                // All the activity to be opened outside of an activity
125
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
122
                 // Validate that the device can open the file
126
                 // Validate that the device can open the file
123
                 PackageManager pm = getCurrentActivity().getPackageManager();
127
                 PackageManager pm = getCurrentActivity().getPackageManager();
124
                 if (intent.resolveActivity(pm) != null) {
128
                 if (intent.resolveActivity(pm) != null) {
409
     public void getSDCardApplicationDir(Promise promise) {
413
     public void getSDCardApplicationDir(Promise promise) {
410
         RNFetchBlobFS.getSDCardApplicationDir(this.getReactApplicationContext(), promise);
414
         RNFetchBlobFS.getSDCardApplicationDir(this.getReactApplicationContext(), promise);
411
     }
415
     }
412
-}
416
+}

+ 37
- 24
android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java View File

21
 import com.facebook.react.modules.core.DeviceEventManagerModule;
21
 import com.facebook.react.modules.core.DeviceEventManagerModule;
22
 
22
 
23
 import java.io.*;
23
 import java.io.*;
24
-import java.nio.ByteBuffer;
25
 import java.nio.charset.Charset;
24
 import java.nio.charset.Charset;
26
-import java.nio.charset.CharsetEncoder;
27
 import java.security.MessageDigest;
25
 import java.security.MessageDigest;
28
 import java.util.ArrayList;
26
 import java.util.ArrayList;
29
 import java.util.HashMap;
27
 import java.util.HashMap;
69
                 }
67
                 }
70
             }
68
             }
71
 
69
 
72
-            FileOutputStream fout = new FileOutputStream(f, append);
73
             // write data from a file
70
             // write data from a file
74
             if(encoding.equalsIgnoreCase(RNFetchBlobConst.DATA_ENCODE_URI)) {
71
             if(encoding.equalsIgnoreCase(RNFetchBlobConst.DATA_ENCODE_URI)) {
75
                 String normalizedData = normalizePath(data);
72
                 String normalizedData = normalizePath(data);
76
                 File src = new File(normalizedData);
73
                 File src = new File(normalizedData);
77
                 if (!src.exists()) {
74
                 if (!src.exists()) {
78
                     promise.reject("ENOENT", "No such file '" + path + "' " + "('" + normalizedData + "')");
75
                     promise.reject("ENOENT", "No such file '" + path + "' " + "('" + normalizedData + "')");
79
-                    fout.close();
80
                     return;
76
                     return;
81
                 }
77
                 }
82
-                FileInputStream fin = new FileInputStream(src);
83
                 byte[] buffer = new byte [10240];
78
                 byte[] buffer = new byte [10240];
84
                 int read;
79
                 int read;
85
                 written = 0;
80
                 written = 0;
86
-                while((read = fin.read(buffer)) > 0) {
87
-                    fout.write(buffer, 0, read);
88
-                    written += read;
81
+                FileInputStream fin = null;
82
+                FileOutputStream fout = null;
83
+                try {
84
+                    fin = new FileInputStream(src);
85
+                    fout = new FileOutputStream(f, append);
86
+                    while ((read = fin.read(buffer)) > 0) {
87
+                        fout.write(buffer, 0, read);
88
+                        written += read;
89
+                    }
90
+                } finally {
91
+                    if (fin != null) {
92
+                        fin.close();
93
+                    }
94
+                    if (fout != null) {
95
+                        fout.close();
96
+                    }
89
                 }
97
                 }
90
-                fin.close();
91
             }
98
             }
92
             else {
99
             else {
93
                 byte[] bytes = stringToBytes(data, encoding);
100
                 byte[] bytes = stringToBytes(data, encoding);
94
-                fout.write(bytes);
95
-                written = bytes.length;
101
+                FileOutputStream fout = new FileOutputStream(f, append);
102
+                try {
103
+                    fout.write(bytes);
104
+                    written = bytes.length;
105
+                } finally {
106
+                    fout.close();
107
+                }
96
             }
108
             }
97
-            fout.close();
98
             promise.resolve(written);
109
             promise.resolve(written);
99
         } catch (FileNotFoundException e) {
110
         } catch (FileNotFoundException e) {
100
             // According to https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
111
             // According to https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
129
             }
140
             }
130
 
141
 
131
             FileOutputStream os = new FileOutputStream(f, append);
142
             FileOutputStream os = new FileOutputStream(f, append);
132
-            byte[] bytes = new byte[data.size()];
133
-            for(int i=0;i<data.size();i++) {
134
-                bytes[i] = (byte) data.getInt(i);
143
+            try {
144
+                byte[] bytes = new byte[data.size()];
145
+                for (int i = 0; i < data.size(); i++) {
146
+                    bytes[i] = (byte) data.getInt(i);
147
+                }
148
+                os.write(bytes);
149
+            } finally {
150
+                os.close();
135
             }
151
             }
136
-            os.write(bytes);
137
-            os.close();
138
             promise.resolve(data.size());
152
             promise.resolve(data.size());
139
         } catch (FileNotFoundException e) {
153
         } catch (FileNotFoundException e) {
140
             // According to https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
154
             // According to https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
325
             boolean error = false;
339
             boolean error = false;
326
 
340
 
327
             if (encoding.equalsIgnoreCase("utf8")) {
341
             if (encoding.equalsIgnoreCase("utf8")) {
328
-                CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
329
                 while ((cursor = fs.read(buffer)) != -1) {
342
                 while ((cursor = fs.read(buffer)) != -1) {
330
-                    encoder.encode(ByteBuffer.wrap(buffer).asCharBuffer());
331
                     String chunk = new String(buffer, 0, cursor);
343
                     String chunk = new String(buffer, 0, cursor);
332
                     emitStreamEvent(streamId, "data", chunk);
344
                     emitStreamEvent(streamId, "data", chunk);
333
                     if(tick > 0)
345
                     if(tick > 0)
523
     static void mkdir(String path, Promise promise) {
535
     static void mkdir(String path, Promise promise) {
524
         File dest = new File(path);
536
         File dest = new File(path);
525
         if(dest.exists()) {
537
         if(dest.exists()) {
526
-            promise.reject("EEXIST", dest.isDirectory() ? "Folder" : "File" + " '" + path + "' already exists");
538
+            promise.reject("EEXIST", (dest.isDirectory() ? "Folder" : "File") + " '" + path + "' already exists");
527
             return;
539
             return;
528
         }
540
         }
529
         try {
541
         try {
876
             MessageDigest md = MessageDigest.getInstance(algorithms.get(algorithm));
888
             MessageDigest md = MessageDigest.getInstance(algorithms.get(algorithm));
877
 
889
 
878
             FileInputStream inputStream = new FileInputStream(path);
890
             FileInputStream inputStream = new FileInputStream(path);
879
-            byte[] buffer = new byte[(int)file.length()];
891
+            int chunkSize = 4096 * 256; // 1Mb
892
+            byte[] buffer = new byte[chunkSize];
880
 
893
 
881
             if(file.length() != 0) {
894
             if(file.length() != 0) {
882
-                int read;
883
-                while ((read = inputStream.read(buffer)) != -1) {
884
-                    md.update(buffer, 0, read);
895
+                int bytesRead;
896
+                while ((bytesRead = inputStream.read(buffer)) != -1) {
897
+                    md.update(buffer, 0, bytesRead);
885
                 }
898
                 }
886
             }
899
             }
887
 
900
 

+ 45
- 45
android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java View File

36
 import java.net.SocketException;
36
 import java.net.SocketException;
37
 import java.net.SocketTimeoutException;
37
 import java.net.SocketTimeoutException;
38
 import java.net.URL;
38
 import java.net.URL;
39
-import java.nio.ByteBuffer;
40
-import java.nio.charset.CharacterCodingException;
41
-import java.nio.charset.Charset;
42
-import java.nio.charset.CharsetEncoder;
43
 import java.security.KeyStore;
39
 import java.security.KeyStore;
44
 import java.util.ArrayList;
40
 import java.util.ArrayList;
45
 import java.util.Arrays;
41
 import java.util.Arrays;
502
                         // encoding will somehow break the UTF8 string format, to encode UTF8
498
                         // encoding will somehow break the UTF8 string format, to encode UTF8
503
                         // string correctly, we should do URL encoding before BASE64.
499
                         // string correctly, we should do URL encoding before BASE64.
504
                         byte[] b = resp.body().bytes();
500
                         byte[] b = resp.body().bytes();
505
-                        CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
506
                         if(responseFormat == ResponseFormat.BASE64) {
501
                         if(responseFormat == ResponseFormat.BASE64) {
507
                             callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_BASE64, android.util.Base64.encodeToString(b, Base64.NO_WRAP));
502
                             callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_BASE64, android.util.Base64.encodeToString(b, Base64.NO_WRAP));
508
                             return;
503
                             return;
509
                         }
504
                         }
510
-                        try {
511
-                            encoder.encode(ByteBuffer.wrap(b).asCharBuffer());
512
-                            // if the data contains invalid characters the following lines will be
513
-                            // skipped.
514
-                            String utf8 = new String(b);
515
-                            callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_UTF8, utf8);
516
-                        }
517
-                        // This usually mean the data is contains invalid unicode characters, it's
518
-                        // binary data
519
-                        catch(CharacterCodingException ignored) {
520
-                            if(responseFormat == ResponseFormat.UTF8) {
521
-                                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_UTF8, "");
522
-                            }
523
-                            else {
524
-                                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_BASE64, android.util.Base64.encodeToString(b, Base64.NO_WRAP));
525
-                            }
526
-                        }
505
+                        String utf8 = new String(b);
506
+                        callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_UTF8, utf8);
527
                     }
507
                     }
528
                 } catch (IOException e) {
508
                 } catch (IOException e) {
529
                     callback.invoke("RNFetchBlob failed to encode response data to BASE64 string.", null);
509
                     callback.invoke("RNFetchBlob failed to encode response data to BASE64 string.", null);
530
                 }
510
                 }
531
                 break;
511
                 break;
532
             case FileStorage:
512
             case FileStorage:
513
+                ResponseBody responseBody = resp.body();
514
+
533
                 try {
515
                 try {
534
                     // In order to write response data to `destPath` we have to invoke this method.
516
                     // In order to write response data to `destPath` we have to invoke this method.
535
                     // It uses customized response body which is able to report download progress
517
                     // It uses customized response body which is able to report download progress
536
                     // and write response data to destination path.
518
                     // and write response data to destination path.
537
-                    resp.body().bytes();
519
+                    responseBody.bytes();
538
                 } catch (Exception ignored) {
520
                 } catch (Exception ignored) {
539
 //                    ignored.printStackTrace();
521
 //                    ignored.printStackTrace();
540
                 }
522
                 }
541
-                this.destPath = this.destPath.replace("?append=true", "");
542
-                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
523
+
524
+                RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
525
+
526
+                if(rnFetchBlobFileResp != null && rnFetchBlobFileResp.isDownloadComplete() == false){
527
+                    callback.invoke("RNFetchBlob failed. Download interrupted.", null);
528
+                }
529
+                else {
530
+                    this.destPath = this.destPath.replace("?append=true", "");
531
+                    callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
532
+                }
543
                 break;
533
                 break;
544
             default:
534
             default:
545
                 try {
535
                 try {
666
                 DownloadManager dm = (DownloadManager) appCtx.getSystemService(Context.DOWNLOAD_SERVICE);
656
                 DownloadManager dm = (DownloadManager) appCtx.getSystemService(Context.DOWNLOAD_SERVICE);
667
                 dm.query(query);
657
                 dm.query(query);
668
                 Cursor c = dm.query(query);
658
                 Cursor c = dm.query(query);
669
-
659
+                // #236 unhandled null check for DownloadManager.query() return value
660
+                if (c == null) {
661
+                    this.callback.invoke("Download manager failed to download from  " + this.url + ". Query was unsuccessful ", null, null);
662
+                    return;
663
+                }
670
 
664
 
671
                 String filePath = null;
665
                 String filePath = null;
672
-                // the file exists in media content database
673
-                if (c.moveToFirst()) {
674
-                    // #297 handle failed request
675
-                    int statusCode = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
676
-                    if(statusCode == DownloadManager.STATUS_FAILED) {
677
-                        this.callback.invoke("Download manager failed to download from  " + this.url + ". Status Code = " + statusCode, null, null);
678
-                        return;
679
-                    }
680
-                    String contentUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
681
-                    if ( contentUri != null &&
682
-                            options.addAndroidDownloads.hasKey("mime") &&
683
-                            options.addAndroidDownloads.getString("mime").contains("image")) {
684
-                        Uri uri = Uri.parse(contentUri);
685
-                        Cursor cursor = appCtx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null);
686
-                        // use default destination of DownloadManager
687
-                        if (cursor != null) {
688
-                            cursor.moveToFirst();
689
-                            filePath = cursor.getString(0);
690
-                            cursor.close();
666
+                try {    
667
+                    // the file exists in media content database
668
+                    if (c.moveToFirst()) {
669
+                        // #297 handle failed request
670
+                        int statusCode = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
671
+                        if(statusCode == DownloadManager.STATUS_FAILED) {
672
+                            this.callback.invoke("Download manager failed to download from  " + this.url + ". Status Code = " + statusCode, null, null);
673
+                            return;
674
+                        }
675
+                        String contentUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
676
+                        if ( contentUri != null &&
677
+                                options.addAndroidDownloads.hasKey("mime") &&
678
+                                options.addAndroidDownloads.getString("mime").contains("image")) {
679
+                            Uri uri = Uri.parse(contentUri);
680
+                            Cursor cursor = appCtx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null);
681
+                            // use default destination of DownloadManager
682
+                            if (cursor != null) {
683
+                                cursor.moveToFirst();
684
+                                filePath = cursor.getString(0);
685
+                                cursor.close();
686
+                            }
691
                         }
687
                         }
692
                     }
688
                     }
689
+                } finally {
690
+                    if (c != null) {
691
+                        c.close();
692
+                    }
693
                 }
693
                 }
694
 
694
 
695
                 // When the file is not found in media content database, check if custom path exists
695
                 // When the file is not found in media content database, check if custom path exists

+ 4
- 0
android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java View File

68
         return originalBody.contentLength();
68
         return originalBody.contentLength();
69
     }
69
     }
70
 
70
 
71
+    public boolean isDownloadComplete() {
72
+        return bytesDownloaded == contentLength();
73
+    }
74
+
71
     @Override
75
     @Override
72
     public BufferedSource source() {
76
     public BufferedSource source() {
73
         ProgressReportingSource countable = new ProgressReportingSource();
77
         ProgressReportingSource countable = new ProgressReportingSource();

+ 18
- 5
android/src/main/java/com/RNFetchBlob/Utils/PathResolver.java View File

37
             }
37
             }
38
             // DownloadsProvider
38
             // DownloadsProvider
39
             else if (isDownloadsDocument(uri)) {
39
             else if (isDownloadsDocument(uri)) {
40
+                try {
41
+                    final String id = DocumentsContract.getDocumentId(uri);
42
+                    //Starting with Android O, this "id" is not necessarily a long (row number),
43
+                    //but might also be a "raw:/some/file/path" URL
44
+                    if (id != null && id.startsWith("raw:/")) {
45
+                        Uri rawuri = Uri.parse(id);
46
+                        String path = rawuri.getPath();
47
+                        return path;
48
+                    }
49
+                    final Uri contentUri = ContentUris.withAppendedId(
50
+                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
40
 
51
 
41
-                final String id = DocumentsContract.getDocumentId(uri);
42
-                final Uri contentUri = ContentUris.withAppendedId(
43
-                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
44
-
45
-                return getDataColumn(context, contentUri, null, null);
52
+                    return getDataColumn(context, contentUri, null, null);
53
+                }
54
+                catch (Exception ex) {
55
+                    //something went wrong, but android should still be able to handle the original uri by returning null here (see readFile(...))
56
+                    return null;
57
+                }
58
+                
46
             }
59
             }
47
             // MediaProvider
60
             // MediaProvider
48
             else if (isMediaDocument(uri)) {
61
             else if (isMediaDocument(uri)) {

+ 4
- 1
android/src/main/res/xml/provider_paths.xml View File

6
     <files-path
6
     <files-path
7
         name="files-path"
7
         name="files-path"
8
         path="." /> <!-- Used to access into application data files -->
8
         path="." /> <!-- Used to access into application data files -->
9
-</paths>
9
+    <cache-path
10
+        name="cache-path"
11
+        path="." /> <!-- Used to access files in cache directory -->
12
+</paths>

+ 14
- 0
fs.js View File

135
   return RNFetchBlob.pathForAppGroup(groupName)
135
   return RNFetchBlob.pathForAppGroup(groupName)
136
 }
136
 }
137
 
137
 
138
+/**
139
+ * Returns the path for the app group synchronous.
140
+ * @param  {string} groupName Name of app group
141
+ * @return {string} Path of App Group dir
142
+ */
143
+function syncPathAppGroup(groupName: string): string {
144
+  if (Platform.OS === 'ios') {
145
+    return RNFetchBlob.syncPathAppGroup(groupName);
146
+  } else {
147
+    return '';
148
+  }
149
+}
150
+
138
 /**
151
 /**
139
  * Wrapper method of readStream.
152
  * Wrapper method of readStream.
140
  * @param  {string} path Path of the file.
153
  * @param  {string} path Path of the file.
402
   writeFile,
415
   writeFile,
403
   appendFile,
416
   appendFile,
404
   pathForAppGroup,
417
   pathForAppGroup,
418
+  syncPathAppGroup,
405
   readFile,
419
   readFile,
406
   hash,
420
   hash,
407
   exists,
421
   exists,

+ 10
- 0
index.d.ts View File

96
      */
96
      */
97
     flush(): void;
97
     flush(): void;
98
     respInfo: RNFetchBlobResponseInfo;
98
     respInfo: RNFetchBlobResponseInfo;
99
+    info(): RNFetchBlobResponseInfo;
99
     session(name: string): RNFetchBlobSession | null;
100
     session(name: string): RNFetchBlobSession | null;
100
     /**
101
     /**
101
      * Read file content with given encoding, if the response does not contains
102
      * Read file content with given encoding, if the response does not contains
293
     removeCookies(domain?: string): Promise<null>;
294
     removeCookies(domain?: string): Promise<null>;
294
 }
295
 }
295
 
296
 
297
+type HashAlgorithm = "md5" | "sha1" | "sha224" | "sha256" | "sha384" | "sha512";
296
 export interface FS {
298
 export interface FS {
297
     RNFetchBlobSession: RNFetchBlobSession;
299
     RNFetchBlobSession: RNFetchBlobSession;
298
 
300
 
316
 
318
 
317
     ls(path: string): Promise<string[]>;
319
     ls(path: string): Promise<string[]>;
318
 
320
 
321
+    /**
322
+     * Read the file from the given path and calculate a cryptographic hash sum over its contents.
323
+     *
324
+     * @param path Path to the file
325
+     * @param algorithm The hash algorithm to use
326
+     */
327
+    hash(path: string, algorithm: HashAlgorithm): Promise<string>;
328
+
319
     /**
329
     /**
320
      * Create file stream from file at `path`.
330
      * Create file stream from file at `path`.
321
      * @param  path   The file path.
331
      * @param  path   The file path.

+ 7
- 0
index.js View File

228
     return fetchFile(options, method, url, headers, body)
228
     return fetchFile(options, method, url, headers, body)
229
   }
229
   }
230
 
230
 
231
+  let promiseResolve;
232
+  let promiseReject;
233
+
231
   // from remote HTTP(S)
234
   // from remote HTTP(S)
232
   let promise = new Promise((resolve, reject) => {
235
   let promise = new Promise((resolve, reject) => {
236
+    promiseResolve = resolve;
237
+    promiseReject = reject;
238
+
233
     let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
239
     let nativeMethodName = Array.isArray(body) ? 'fetchBlobForm' : 'fetchBlob'
234
 
240
 
235
     // on progress event listener
241
     // on progress event listener
370
     subscriptionUpload.remove()
376
     subscriptionUpload.remove()
371
     stateEvent.remove()
377
     stateEvent.remove()
372
     RNFetchBlob.cancelRequest(taskId, fn)
378
     RNFetchBlob.cancelRequest(taskId, fn)
379
+    promiseReject(new Error("canceled"))
373
   }
380
   }
374
   promise.taskId = taskId
381
   promise.taskId = taskId
375
 
382
 

+ 19
- 2
ios/RNFetchBlob/RNFetchBlob.m View File

68
 - (NSDictionary *)constantsToExport
68
 - (NSDictionary *)constantsToExport
69
 {
69
 {
70
     return @{
70
     return @{
71
-             @"MainBundleDir" : [RNFetchBlobFS getMainBundleDir],
71
+             @"CacheDir" : [RNFetchBlobFS getCacheDir],
72
              @"DocumentDir": [RNFetchBlobFS getDocumentDir],
72
              @"DocumentDir": [RNFetchBlobFS getDocumentDir],
73
-             @"CacheDir" : [RNFetchBlobFS getCacheDir]
73
+             @"DownloadDir" : [RNFetchBlobFS getDownloadDir],
74
+             @"LibraryDir" : [RNFetchBlobFS getLibraryDir],
75
+             @"MainBundleDir" : [RNFetchBlobFS getMainBundleDir],
76
+             @"MovieDir" : [RNFetchBlobFS getMovieDir],
77
+             @"MusicDir" : [RNFetchBlobFS getMusicDir],
78
+             @"PictureDir" : [RNFetchBlobFS getPictureDir],
74
              };
79
              };
75
 }
80
 }
76
 
81
 
228
     }
233
     }
229
 }
234
 }
230
 
235
 
236
+#pragma mark - fs.syncPathAppGroup
237
+RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(syncPathAppGroup:(NSString *)groupName) {
238
+    NSURL *pathUrl = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupName];
239
+    NSString *path = [pathUrl path];
240
+
241
+    if(path) {
242
+        return path;
243
+    } else {
244
+        return @"";
245
+    }
246
+}
247
+
231
 #pragma mark - fs.exists
248
 #pragma mark - fs.exists
232
 RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callback) {
249
 RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callback) {
233
     [RNFetchBlobFS exists:path callback:callback];
250
     [RNFetchBlobFS exists:path callback:callback];

+ 7
- 2
ios/RNFetchBlobFS.h View File

46
 @property (nonatomic) BOOL appendData;
46
 @property (nonatomic) BOOL appendData;
47
 
47
 
48
 // get dirs
48
 // get dirs
49
-+ (NSString *) getMainBundleDir;
50
-+ (NSString *) getTempPath;
51
 + (NSString *) getCacheDir;
49
 + (NSString *) getCacheDir;
52
 + (NSString *) getDocumentDir;
50
 + (NSString *) getDocumentDir;
51
++ (NSString *) getDownloadDir;
52
++ (NSString *) getLibraryDir;
53
++ (NSString *) getMainBundleDir;
54
++ (NSString *) getMovieDir;
55
++ (NSString *) getMusicDir;
56
++ (NSString *) getPictureDir;
57
++ (NSString *) getTempPath;
53
 + (NSString *) getTempPath:(NSString*)taskId withExtension:(NSString *)ext;
58
 + (NSString *) getTempPath:(NSString*)taskId withExtension:(NSString *)ext;
54
 + (NSString *) getPathOfAsset:(NSString *)assetURI;
59
 + (NSString *) getPathOfAsset:(NSString *)assetURI;
55
 + (NSString *) getPathForAppGroup:(NSString *)groupName;
60
 + (NSString *) getPathForAppGroup:(NSString *)groupName;

+ 8
- 0
ios/RNFetchBlobFS.m View File

104
     return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
104
     return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
105
 }
105
 }
106
 
106
 
107
++ (NSString *) getDownloadDir {
108
+    return [NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, YES) firstObject];
109
+}
110
+
111
++ (NSString *) getLibraryDir {
112
+    return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
113
+}
114
+
107
 + (NSString *) getMusicDir {
115
 + (NSString *) getMusicDir {
108
     return [NSSearchPathForDirectoriesInDomains(NSMusicDirectory, NSUserDomainMask, YES) firstObject];
116
     return [NSSearchPathForDirectoriesInDomains(NSMusicDirectory, NSUserDomainMask, YES) firstObject];
109
 }
117
 }

+ 1
- 1
ios/RNFetchBlobReqBuilder.m View File

69
                 [mheaders setValue:[NSString stringWithFormat:@"%lu",[postData length]] forKey:@"Content-Length"];
69
                 [mheaders setValue:[NSString stringWithFormat:@"%lu",[postData length]] forKey:@"Content-Length"];
70
                 [mheaders setValue:@"100-continue" forKey:@"Expect"];
70
                 [mheaders setValue:@"100-continue" forKey:@"Expect"];
71
                 // appaned boundary to content-type
71
                 // appaned boundary to content-type
72
-                [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@", boundary] forKey:@"content-type"];
72
+                [mheaders setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forKey:@"content-type"];
73
                 [request setHTTPMethod: method];
73
                 [request setHTTPMethod: method];
74
                 [request setAllHTTPHeaderFields:mheaders];
74
                 [request setAllHTTPHeaderFields:mheaders];
75
                 onComplete(request, [formData length]);
75
                 onComplete(request, [formData length]);

+ 1
- 6
package.json View File

1
 {
1
 {
2
   "name": "rn-fetch-blob",
2
   "name": "rn-fetch-blob",
3
-  "version": "0.10.16",
3
+  "version": "0.11.1",
4
   "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.",
4
   "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.",
5
   "main": "index.js",
5
   "main": "index.js",
6
   "scripts": {
6
   "scripts": {
21
     "filestream",
21
     "filestream",
22
     "image header"
22
     "image header"
23
   ],
23
   ],
24
-  "rnpm": {
25
-    "commands": {
26
-      "prelink": "node ./node_modules/rn-fetch-blob/scripts/prelink.js"
27
-    }
28
-  },
29
   "repository": {
24
   "repository": {
30
     "url": "https://github.com/joltup/rn-fetch-blob.git"
25
     "url": "https://github.com/joltup/rn-fetch-blob.git"
31
   },
26
   },

+ 7
- 0
react-native.config.js View File

1
+module.exports = {
2
+  dependency: {
3
+    hooks: {
4
+      prelink: 'node ./node_modules/rn-fetch-blob/scripts/prelink.js',
5
+    },
6
+  },
7
+};

+ 7
- 4
rn-fetch-blob.podspec View File

1
+require "json"
2
+package = JSON.parse(File.read('package.json'))
3
+
1
 Pod::Spec.new do |s|
4
 Pod::Spec.new do |s|
2
-  s.name             = "rn-fetch-blob"
3
-  s.version          = "0.10.16"
4
-  s.summary          = "A project committed to make file acess and data transfer easier, effiecient for React Native developers."
5
+  s.name             = package['name']
6
+  s.version          = package['version']
7
+  s.summary          = package['description']
5
   s.requires_arc = true
8
   s.requires_arc = true
6
   s.license      = 'MIT'
9
   s.license      = 'MIT'
7
   s.homepage     = 'n/a'
10
   s.homepage     = 'n/a'
8
-  s.source       = { :git => "https://github.com/joltup/rn-fetch-blob", :tag => 'v0.10.16'}
11
+  s.source       = { :git => "https://github.com/joltup/rn-fetch-blob" }
9
   s.author       = 'Joltup'
12
   s.author       = 'Joltup'
10
   s.source_files = 'ios/**/*.{h,m}'
13
   s.source_files = 'ios/**/*.{h,m}'
11
   s.platform     = :ios, "8.0"
14
   s.platform     = :ios, "8.0"