Browse Source

Bug fix for download interruption promise rejection

Sushant Gupta 5 years ago
parent
commit
d03a502bad

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

530
                 }
530
                 }
531
                 break;
531
                 break;
532
             case FileStorage:
532
             case FileStorage:
533
+                ResponseBody responseBody = resp.body();
534
+
533
                 try {
535
                 try {
534
                     // In order to write response data to `destPath` we have to invoke this method.
536
                     // 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
537
                     // It uses customized response body which is able to report download progress
536
                     // and write response data to destination path.
538
                     // and write response data to destination path.
537
-                    resp.body().bytes();
539
+                    responseBody.bytes();
538
                 } catch (Exception ignored) {
540
                 } catch (Exception ignored) {
539
 //                    ignored.printStackTrace();
541
 //                    ignored.printStackTrace();
540
                 }
542
                 }
541
-                this.destPath = this.destPath.replace("?append=true", "");
542
-                callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
543
+
544
+                RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
545
+
546
+                if(rnFetchBlobFileResp != null && rnFetchBlobFileResp.isDownloadComplete() == false){
547
+                    callback.invoke("RNFetchBlob failed. Download interrupted.", null);
548
+                }
549
+                else {
550
+                    this.destPath = this.destPath.replace("?append=true", "");
551
+                    callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
552
+                }
543
                 break;
553
                 break;
544
             default:
554
             default:
545
                 try {
555
                 try {

+ 41
- 7
android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java View File

33
     long bytesDownloaded = 0;
33
     long bytesDownloaded = 0;
34
     ReactApplicationContext rctContext;
34
     ReactApplicationContext rctContext;
35
     FileOutputStream ofStream;
35
     FileOutputStream ofStream;
36
+    boolean isEndMarkerReceived;
36
 
37
 
37
     public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
38
     public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
38
         super();
39
         super();
41
         this.originalBody = body;
42
         this.originalBody = body;
42
         assert path != null;
43
         assert path != null;
43
         this.mPath = path;
44
         this.mPath = path;
45
+        this.isEndMarkerReceived = false;
44
         if (path != null) {
46
         if (path != null) {
45
             boolean appendToExistingFile = !overwrite;
47
             boolean appendToExistingFile = !overwrite;
46
             path = path.replace("?append=true", "");
48
             path = path.replace("?append=true", "");
68
         return originalBody.contentLength();
70
         return originalBody.contentLength();
69
     }
71
     }
70
 
72
 
73
+    public boolean isDownloadComplete() {
74
+        return (bytesDownloaded == contentLength()) // Case of non-chunked downloads
75
+                || (contentLength() == -1 && isEndMarkerReceived); // Case of chunked downloads
76
+    }
77
+
71
     @Override
78
     @Override
72
     public BufferedSource source() {
79
     public BufferedSource source() {
73
         ProgressReportingSource countable = new ProgressReportingSource();
80
         ProgressReportingSource countable = new ProgressReportingSource();
83
                 bytesDownloaded += read > 0 ? read : 0;
90
                 bytesDownloaded += read > 0 ? read : 0;
84
                 if (read > 0) {
91
                 if (read > 0) {
85
                     ofStream.write(bytes, 0, (int) read);
92
                     ofStream.write(bytes, 0, (int) read);
93
+                } else if (contentLength() == -1 && read == -1) {
94
+                    // End marker has been received for chunked download
95
+                    isEndMarkerReceived = true;
86
                 }
96
                 }
87
                 RNFetchBlobProgressConfig reportConfig = RNFetchBlobReq.getReportProgress(mTaskId);
97
                 RNFetchBlobProgressConfig reportConfig = RNFetchBlobReq.getReportProgress(mTaskId);
88
-                if (reportConfig != null && contentLength() != 0 &&reportConfig.shouldReport(bytesDownloaded / contentLength())) {
89
-                    WritableMap args = Arguments.createMap();
90
-                    args.putString("taskId", mTaskId);
91
-                    args.putString("written", String.valueOf(bytesDownloaded));
92
-                    args.putString("total", String.valueOf(contentLength()));
93
-                    rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
94
-                            .emit(RNFetchBlobConst.EVENT_PROGRESS, args);
98
+
99
+                if (contentLength() != 0) {
100
+
101
+                    // For non-chunked download, progress is received / total
102
+                    // For chunked download, progress can be either 0 (started) or 1 (ended)
103
+                    float progress = (contentLength() != -1) ? bytesDownloaded / contentLength() : ( ( isEndMarkerReceived ) ? 1 : 0 );
104
+
105
+                    if (reportConfig != null && reportConfig.shouldReport(progress /* progress */)) {
106
+                        if (contentLength() != -1) {
107
+                            // For non-chunked downloads
108
+                            reportProgress(mTaskId, bytesDownloaded, contentLength());
109
+                        } else {
110
+                            // For chunked downloads
111
+                            if (!isEndMarkerReceived) {
112
+                                reportProgress(mTaskId, 0, contentLength());
113
+                            } else{
114
+                                reportProgress(mTaskId, bytesDownloaded, bytesDownloaded);
115
+                            }
116
+                        }
117
+                    }
118
+
95
                 }
119
                 }
120
+
96
                 return read;
121
                 return read;
97
             } catch(Exception ex) {
122
             } catch(Exception ex) {
98
                 return -1;
123
                 return -1;
99
             }
124
             }
100
         }
125
         }
101
 
126
 
127
+        private void reportProgress(String taskId, long bytesDownloaded, long contentLength) {
128
+            WritableMap args = Arguments.createMap();
129
+            args.putString("taskId", taskId);
130
+            args.putString("written", String.valueOf(bytesDownloaded));
131
+            args.putString("total", String.valueOf(contentLength));
132
+            rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
133
+                    .emit(RNFetchBlobConst.EVENT_PROGRESS, args);
134
+        }
135
+
102
         @Override
136
         @Override
103
         public Timeout timeout() {
137
         public Timeout timeout() {
104
             return null;
138
             return null;