react-native-blob-util 0.24.6 → 0.24.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +96 -96
- package/LICENSE +21 -21
- package/Migration.md +41 -41
- package/NuGet.config +11 -11
- package/README.md +1109 -1109
- package/android/gradle.properties +1 -1
- package/android/src/main/AndroidManifest.xml +37 -37
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java +59 -59
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConst.java +20 -20
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java +9 -9
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilImpl.java +431 -431
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilProgressConfig.java +39 -39
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +1092 -1092
- package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilStream.java +48 -43
- package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilDefaultResp.java +98 -98
- package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java +183 -166
- package/android/src/main/java/com/ReactNativeBlobUtil/Utils/FileDescription.java +19 -19
- package/android/src/main/java/com/ReactNativeBlobUtil/Utils/FileProvider.java +4 -4
- package/android/src/main/java/com/ReactNativeBlobUtil/Utils/MimeType.java +70 -70
- package/android/src/main/java/com/ReactNativeBlobUtil/Utils/PathResolver.java +223 -223
- package/android/src/main/java/com/ReactNativeBlobUtil/Utils/Tls12SocketFactory.java +68 -68
- package/android/src/main/res/values/strings.xml +3 -3
- package/android/src/main/res/xml/provider_paths.xml +12 -12
- package/android.js +58 -58
- package/class/ReactNativeBlobUtilCanceledFetchError.js +9 -9
- package/class/ReactNativeBlobUtilFile.js +5 -5
- package/class/ReactNativeBlobUtilSession.js +68 -68
- package/class/ReactNativeBlobUtilWriteStream.js +50 -50
- package/class/StatefulPromise.js +7 -7
- package/codegenSpecs/NativeBlobUtils.js +86 -86
- package/components/Fetch.onPress.js +10 -10
- package/components/Fetch.when.js +15 -15
- package/fetch.js +350 -350
- package/fs.js +480 -480
- package/index.d.ts +881 -881
- package/index.js +64 -64
- package/index.js.flow +192 -192
- package/index.web.js +1 -1
- package/ios/PrivacyInfo.xcprivacy +28 -28
- package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.h +55 -55
- package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.mm +1013 -1013
- package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +405 -405
- package/ios/ReactNativeBlobUtilConst.h +58 -58
- package/ios/ReactNativeBlobUtilConst.mm +47 -47
- package/ios/ReactNativeBlobUtilFS.h +108 -108
- package/ios/ReactNativeBlobUtilFS.mm +1080 -1080
- package/ios/ReactNativeBlobUtilFileTransformer.h +23 -23
- package/ios/ReactNativeBlobUtilFileTransformer.mm +20 -20
- package/ios/ReactNativeBlobUtilNetwork.h +50 -49
- package/ios/ReactNativeBlobUtilNetwork.mm +173 -159
- package/ios/ReactNativeBlobUtilProgress.h +32 -32
- package/ios/ReactNativeBlobUtilProgress.mm +57 -57
- package/ios/ReactNativeBlobUtilReqBuilder.h +37 -37
- package/ios/ReactNativeBlobUtilReqBuilder.mm +292 -292
- package/ios/ReactNativeBlobUtilRequest.h +48 -48
- package/ios/ReactNativeBlobUtilRequest.mm +586 -584
- package/ios.js +61 -61
- package/json-stream.js +42 -42
- package/lib/oboe-browser.js +2703 -2703
- package/mediacollection.js +36 -36
- package/package.json +86 -77
- package/polyfill/Blob.js +362 -362
- package/polyfill/Event.js +11 -11
- package/polyfill/EventTarget.js +78 -78
- package/polyfill/Fetch.js +219 -219
- package/polyfill/File.js +27 -27
- package/polyfill/FileReader.js +91 -91
- package/polyfill/ProgressEvent.js +32 -32
- package/polyfill/XMLHttpRequest.js +466 -466
- package/polyfill/XMLHttpRequestEventTarget.js +126 -126
- package/polyfill/index.js +11 -11
- package/react-native-blob-util.podspec +48 -48
- package/types.js +69 -69
- package/utils/log.js +40 -40
- package/utils/unicode.js +7 -7
- package/utils/uri.js +33 -33
- package/utils/uuid.js +5 -4
- package/windows/ExperimentalFeatures.props +33 -33
- package/windows/README.md +2 -2
- package/windows/ReactNativeBlobUtil/PropertySheet.props +15 -15
- package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.cpp +1836 -1836
- package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.def +3 -3
- package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.h +372 -372
- package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj +139 -139
- package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj.filters +43 -43
- package/windows/ReactNativeBlobUtil/ReactPackageProvider.cpp +20 -20
- package/windows/ReactNativeBlobUtil/ReactPackageProvider.h +24 -24
- package/windows/ReactNativeBlobUtil/ReactPackageProvider.idl +9 -9
- package/windows/ReactNativeBlobUtil/codegen/.clang-format +1 -1
- package/windows/ReactNativeBlobUtil/codegen/NativeBlobUtilsDataTypes.g.h +42 -42
- package/windows/ReactNativeBlobUtil/codegen/NativeBlobUtilsSpec.g.h +353 -353
- package/windows/ReactNativeBlobUtil/packages.config +3 -3
- package/windows/ReactNativeBlobUtil/packages.lock.json +59 -59
- package/windows/ReactNativeBlobUtil/pch.cpp +1 -1
- package/windows/ReactNativeBlobUtil/pch.h +30 -30
- package/windows/ReactNativeBlobUtil/resource.h +5 -5
- package/windows/ReactNativeBlobUtil/targetver.h +8 -8
- package/windows/ReactNativeBlobUtil.sln +43 -43
|
@@ -149,51 +149,56 @@ public class ReactNativeBlobUtilStream {
|
|
|
149
149
|
*/
|
|
150
150
|
void writeStream(String path, String encoding, boolean append, Callback callback) {
|
|
151
151
|
String resolved = ReactNativeBlobUtilUtils.normalizePath(path);
|
|
152
|
-
if (resolved != null)
|
|
153
|
-
path = resolved;
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
callback.invoke("EISDIR", "Expecting a file but '" + path + "' is a directory");
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
OutputStream fs;
|
|
176
|
-
if (resolved != null && path.startsWith(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET)) {
|
|
177
|
-
fs = ReactNativeBlobUtilImpl.RCTContext.getAssets().openFd(path.replace(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET, "")).createOutputStream ();
|
|
178
|
-
}
|
|
179
|
-
// fix issue 287
|
|
180
|
-
else if (resolved == null) {
|
|
181
|
-
fs = ReactNativeBlobUtilImpl.RCTContext.getContentResolver().openOutputStream(Uri.parse(path));
|
|
182
|
-
} else {
|
|
183
|
-
fs = new FileOutputStream(path, append);
|
|
184
|
-
}
|
|
185
|
-
this.encoding = encoding;
|
|
186
|
-
String streamId = UUID.randomUUID().toString();
|
|
187
|
-
ReactNativeBlobUtilStream.fileStreams.put(streamId, this);
|
|
188
|
-
this.writeStreamInstance = fs;
|
|
152
|
+
if (resolved != null)
|
|
153
|
+
path = resolved;
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
OutputStream fs;
|
|
157
|
+
if (resolved != null && path.startsWith(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET)) {
|
|
158
|
+
fs = ReactNativeBlobUtilImpl.RCTContext.getAssets().openFd(path.replace(ReactNativeBlobUtilConst.FILE_PREFIX_BUNDLE_ASSET, "")).createOutputStream ();
|
|
159
|
+
}
|
|
160
|
+
// fix issue 287
|
|
161
|
+
else if (resolved == null) {
|
|
162
|
+
fs = ReactNativeBlobUtilImpl.RCTContext.getContentResolver().openOutputStream(Uri.parse(path));
|
|
163
|
+
} else {
|
|
164
|
+
File dest = prepareOutputFile(path);
|
|
165
|
+
fs = new FileOutputStream(dest, append);
|
|
166
|
+
}
|
|
167
|
+
this.encoding = encoding;
|
|
168
|
+
String streamId = UUID.randomUUID().toString();
|
|
169
|
+
ReactNativeBlobUtilStream.fileStreams.put(streamId, this);
|
|
170
|
+
this.writeStreamInstance = fs;
|
|
189
171
|
callback.invoke(null, null, streamId);
|
|
190
172
|
} catch (Exception err) {
|
|
191
|
-
callback.invoke("EUNSPECIFIED", "Failed to create write stream at path `" + path + "`; " + err.getLocalizedMessage());
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
173
|
+
callback.invoke("EUNSPECIFIED", "Failed to create write stream at path `" + path + "`; " + err.getLocalizedMessage());
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private static File prepareOutputFile(String path) throws IOException {
|
|
178
|
+
File file = new File(path).getCanonicalFile();
|
|
179
|
+
File parent = file.getParentFile();
|
|
180
|
+
|
|
181
|
+
if (parent == null) {
|
|
182
|
+
throw new IOException("Invalid output path: " + path);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!parent.exists() && !parent.mkdirs() && !parent.exists()) {
|
|
186
|
+
throw new IOException("Failed to create parent directory of '" + path + "'");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (file.exists() && file.isDirectory()) {
|
|
190
|
+
throw new IOException("Expecting a file but '" + path + "' is a directory");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!file.exists() && !file.createNewFile() && !file.exists()) {
|
|
194
|
+
throw new IOException("File '" + path + "' does not exist and could not be created");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return file;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Write a chunk of data into a file stream.
|
|
197
202
|
*
|
|
198
203
|
* @param streamId File stream ID
|
|
199
204
|
* @param data Data chunk in string format
|
package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilDefaultResp.java
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
package com.ReactNativeBlobUtil.Response;
|
|
2
|
-
|
|
3
|
-
import com.ReactNativeBlobUtil.ReactNativeBlobUtilConst;
|
|
4
|
-
import com.ReactNativeBlobUtil.ReactNativeBlobUtilProgressConfig;
|
|
5
|
-
import com.ReactNativeBlobUtil.ReactNativeBlobUtilReq;
|
|
6
|
-
import com.facebook.react.bridge.Arguments;
|
|
7
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
-
import com.facebook.react.bridge.WritableMap;
|
|
9
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
10
|
-
|
|
11
|
-
import java.io.IOException;
|
|
12
|
-
import java.nio.charset.Charset;
|
|
13
|
-
|
|
14
|
-
import okhttp3.MediaType;
|
|
15
|
-
import okhttp3.ResponseBody;
|
|
16
|
-
import okio.Buffer;
|
|
17
|
-
import okio.BufferedSource;
|
|
18
|
-
import okio.Okio;
|
|
19
|
-
import okio.Source;
|
|
20
|
-
import okio.Timeout;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Created by wkh237 on 2016/7/11.
|
|
24
|
-
*/
|
|
25
|
-
public class ReactNativeBlobUtilDefaultResp extends ResponseBody {
|
|
26
|
-
|
|
27
|
-
String mTaskId;
|
|
28
|
-
ReactApplicationContext rctContext;
|
|
29
|
-
ResponseBody originalBody;
|
|
30
|
-
boolean isIncrement = false;
|
|
31
|
-
|
|
32
|
-
public ReactNativeBlobUtilDefaultResp(ReactApplicationContext ctx, String taskId, ResponseBody body, boolean isIncrement) {
|
|
33
|
-
this.rctContext = ctx;
|
|
34
|
-
this.mTaskId = taskId;
|
|
35
|
-
this.originalBody = body;
|
|
36
|
-
this.isIncrement = isIncrement;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@Override
|
|
40
|
-
public MediaType contentType() {
|
|
41
|
-
return originalBody.contentType();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@Override
|
|
45
|
-
public long contentLength() {
|
|
46
|
-
return originalBody.contentLength();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
@Override
|
|
50
|
-
public BufferedSource source() {
|
|
51
|
-
return Okio.buffer(new ProgressReportingSource(originalBody.source()));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
private class ProgressReportingSource implements Source {
|
|
55
|
-
|
|
56
|
-
BufferedSource mOriginalSource;
|
|
57
|
-
long bytesRead = 0;
|
|
58
|
-
|
|
59
|
-
ProgressReportingSource(BufferedSource originalSource) {
|
|
60
|
-
mOriginalSource = originalSource;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
@Override
|
|
64
|
-
public long read(Buffer sink, long byteCount) throws IOException {
|
|
65
|
-
|
|
66
|
-
long read = mOriginalSource.read(sink, byteCount);
|
|
67
|
-
bytesRead += read > 0 ? read : 0;
|
|
68
|
-
ReactNativeBlobUtilProgressConfig reportConfig = ReactNativeBlobUtilReq.getReportProgress(mTaskId);
|
|
69
|
-
long cLen = contentLength();
|
|
70
|
-
if (reportConfig != null && cLen != 0 && reportConfig.shouldReport(bytesRead / contentLength())) {
|
|
71
|
-
WritableMap args = Arguments.createMap();
|
|
72
|
-
args.putString("taskId", mTaskId);
|
|
73
|
-
args.putString("written", String.valueOf(bytesRead));
|
|
74
|
-
args.putString("total", String.valueOf(contentLength()));
|
|
75
|
-
if (isIncrement) {
|
|
76
|
-
args.putString("chunk", sink.readString(Charset.defaultCharset()));
|
|
77
|
-
} else {
|
|
78
|
-
args.putString("chunk", "");
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
82
|
-
.emit(ReactNativeBlobUtilConst.EVENT_PROGRESS, args);
|
|
83
|
-
}
|
|
84
|
-
return read;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
@Override
|
|
88
|
-
public Timeout timeout() {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@Override
|
|
93
|
-
public void close() throws IOException {
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
}
|
|
1
|
+
package com.ReactNativeBlobUtil.Response;
|
|
2
|
+
|
|
3
|
+
import com.ReactNativeBlobUtil.ReactNativeBlobUtilConst;
|
|
4
|
+
import com.ReactNativeBlobUtil.ReactNativeBlobUtilProgressConfig;
|
|
5
|
+
import com.ReactNativeBlobUtil.ReactNativeBlobUtilReq;
|
|
6
|
+
import com.facebook.react.bridge.Arguments;
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
+
import com.facebook.react.bridge.WritableMap;
|
|
9
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
10
|
+
|
|
11
|
+
import java.io.IOException;
|
|
12
|
+
import java.nio.charset.Charset;
|
|
13
|
+
|
|
14
|
+
import okhttp3.MediaType;
|
|
15
|
+
import okhttp3.ResponseBody;
|
|
16
|
+
import okio.Buffer;
|
|
17
|
+
import okio.BufferedSource;
|
|
18
|
+
import okio.Okio;
|
|
19
|
+
import okio.Source;
|
|
20
|
+
import okio.Timeout;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Created by wkh237 on 2016/7/11.
|
|
24
|
+
*/
|
|
25
|
+
public class ReactNativeBlobUtilDefaultResp extends ResponseBody {
|
|
26
|
+
|
|
27
|
+
String mTaskId;
|
|
28
|
+
ReactApplicationContext rctContext;
|
|
29
|
+
ResponseBody originalBody;
|
|
30
|
+
boolean isIncrement = false;
|
|
31
|
+
|
|
32
|
+
public ReactNativeBlobUtilDefaultResp(ReactApplicationContext ctx, String taskId, ResponseBody body, boolean isIncrement) {
|
|
33
|
+
this.rctContext = ctx;
|
|
34
|
+
this.mTaskId = taskId;
|
|
35
|
+
this.originalBody = body;
|
|
36
|
+
this.isIncrement = isIncrement;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@Override
|
|
40
|
+
public MediaType contentType() {
|
|
41
|
+
return originalBody.contentType();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@Override
|
|
45
|
+
public long contentLength() {
|
|
46
|
+
return originalBody.contentLength();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Override
|
|
50
|
+
public BufferedSource source() {
|
|
51
|
+
return Okio.buffer(new ProgressReportingSource(originalBody.source()));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private class ProgressReportingSource implements Source {
|
|
55
|
+
|
|
56
|
+
BufferedSource mOriginalSource;
|
|
57
|
+
long bytesRead = 0;
|
|
58
|
+
|
|
59
|
+
ProgressReportingSource(BufferedSource originalSource) {
|
|
60
|
+
mOriginalSource = originalSource;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@Override
|
|
64
|
+
public long read(Buffer sink, long byteCount) throws IOException {
|
|
65
|
+
|
|
66
|
+
long read = mOriginalSource.read(sink, byteCount);
|
|
67
|
+
bytesRead += read > 0 ? read : 0;
|
|
68
|
+
ReactNativeBlobUtilProgressConfig reportConfig = ReactNativeBlobUtilReq.getReportProgress(mTaskId);
|
|
69
|
+
long cLen = contentLength();
|
|
70
|
+
if (reportConfig != null && cLen != 0 && reportConfig.shouldReport(bytesRead / contentLength())) {
|
|
71
|
+
WritableMap args = Arguments.createMap();
|
|
72
|
+
args.putString("taskId", mTaskId);
|
|
73
|
+
args.putString("written", String.valueOf(bytesRead));
|
|
74
|
+
args.putString("total", String.valueOf(contentLength()));
|
|
75
|
+
if (isIncrement) {
|
|
76
|
+
args.putString("chunk", sink.readString(Charset.defaultCharset()));
|
|
77
|
+
} else {
|
|
78
|
+
args.putString("chunk", "");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
82
|
+
.emit(ReactNativeBlobUtilConst.EVENT_PROGRESS, args);
|
|
83
|
+
}
|
|
84
|
+
return read;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Override
|
|
88
|
+
public Timeout timeout() {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@Override
|
|
93
|
+
public void close() throws IOException {
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java
CHANGED
|
@@ -1,166 +1,183 @@
|
|
|
1
|
-
package com.ReactNativeBlobUtil.Response;
|
|
2
|
-
|
|
3
|
-
import androidx.annotation.NonNull;
|
|
4
|
-
|
|
5
|
-
import com.ReactNativeBlobUtil.ReactNativeBlobUtilConst;
|
|
6
|
-
import com.ReactNativeBlobUtil.ReactNativeBlobUtilProgressConfig;
|
|
7
|
-
import com.ReactNativeBlobUtil.ReactNativeBlobUtilReq;
|
|
8
|
-
import com.facebook.react.bridge.Arguments;
|
|
9
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
-
import com.facebook.react.bridge.WritableMap;
|
|
11
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
12
|
-
|
|
13
|
-
import java.io.File;
|
|
14
|
-
import java.io.FileOutputStream;
|
|
15
|
-
import java.io.IOException;
|
|
16
|
-
|
|
17
|
-
import okhttp3.MediaType;
|
|
18
|
-
import okhttp3.ResponseBody;
|
|
19
|
-
import okio.Buffer;
|
|
20
|
-
import okio.BufferedSource;
|
|
21
|
-
import okio.Okio;
|
|
22
|
-
import okio.Source;
|
|
23
|
-
import okio.Timeout;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Created by wkh237 on 2016/7/11.
|
|
27
|
-
*/
|
|
28
|
-
public class ReactNativeBlobUtilFileResp extends ResponseBody {
|
|
29
|
-
|
|
30
|
-
String mTaskId;
|
|
31
|
-
ResponseBody originalBody;
|
|
32
|
-
String mPath;
|
|
33
|
-
long bytesDownloaded = 0;
|
|
34
|
-
ReactApplicationContext rctContext;
|
|
35
|
-
FileOutputStream ofStream;
|
|
36
|
-
boolean isEndMarkerReceived;
|
|
37
|
-
|
|
38
|
-
public ReactNativeBlobUtilFileResp(ResponseBody body) {
|
|
39
|
-
super();
|
|
40
|
-
this.originalBody = body;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public ReactNativeBlobUtilFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
|
|
44
|
-
super();
|
|
45
|
-
this.rctContext = ctx;
|
|
46
|
-
this.mTaskId = taskId;
|
|
47
|
-
this.originalBody = body;
|
|
48
|
-
assert path != null;
|
|
49
|
-
this.mPath = path;
|
|
50
|
-
this.isEndMarkerReceived = false;
|
|
51
|
-
if (path != null) {
|
|
52
|
-
boolean appendToExistingFile = !overwrite;
|
|
53
|
-
path = path.replace("?append=true", "");
|
|
54
|
-
mPath = path;
|
|
55
|
-
File f =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
1
|
+
package com.ReactNativeBlobUtil.Response;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
|
|
5
|
+
import com.ReactNativeBlobUtil.ReactNativeBlobUtilConst;
|
|
6
|
+
import com.ReactNativeBlobUtil.ReactNativeBlobUtilProgressConfig;
|
|
7
|
+
import com.ReactNativeBlobUtil.ReactNativeBlobUtilReq;
|
|
8
|
+
import com.facebook.react.bridge.Arguments;
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
+
import com.facebook.react.bridge.WritableMap;
|
|
11
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
|
12
|
+
|
|
13
|
+
import java.io.File;
|
|
14
|
+
import java.io.FileOutputStream;
|
|
15
|
+
import java.io.IOException;
|
|
16
|
+
|
|
17
|
+
import okhttp3.MediaType;
|
|
18
|
+
import okhttp3.ResponseBody;
|
|
19
|
+
import okio.Buffer;
|
|
20
|
+
import okio.BufferedSource;
|
|
21
|
+
import okio.Okio;
|
|
22
|
+
import okio.Source;
|
|
23
|
+
import okio.Timeout;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Created by wkh237 on 2016/7/11.
|
|
27
|
+
*/
|
|
28
|
+
public class ReactNativeBlobUtilFileResp extends ResponseBody {
|
|
29
|
+
|
|
30
|
+
String mTaskId;
|
|
31
|
+
ResponseBody originalBody;
|
|
32
|
+
String mPath;
|
|
33
|
+
long bytesDownloaded = 0;
|
|
34
|
+
ReactApplicationContext rctContext;
|
|
35
|
+
FileOutputStream ofStream;
|
|
36
|
+
boolean isEndMarkerReceived;
|
|
37
|
+
|
|
38
|
+
public ReactNativeBlobUtilFileResp(ResponseBody body) {
|
|
39
|
+
super();
|
|
40
|
+
this.originalBody = body;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public ReactNativeBlobUtilFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
|
|
44
|
+
super();
|
|
45
|
+
this.rctContext = ctx;
|
|
46
|
+
this.mTaskId = taskId;
|
|
47
|
+
this.originalBody = body;
|
|
48
|
+
assert path != null;
|
|
49
|
+
this.mPath = path;
|
|
50
|
+
this.isEndMarkerReceived = false;
|
|
51
|
+
if (path != null) {
|
|
52
|
+
boolean appendToExistingFile = !overwrite;
|
|
53
|
+
path = path.replace("?append=true", "");
|
|
54
|
+
mPath = path;
|
|
55
|
+
File f = prepareOutputFile(path);
|
|
56
|
+
ofStream = new FileOutputStream(f, appendToExistingFile);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private static File prepareOutputFile(String path) throws IOException {
|
|
61
|
+
File file = new File(path).getCanonicalFile();
|
|
62
|
+
File parent = file.getParentFile();
|
|
63
|
+
|
|
64
|
+
if (parent == null) {
|
|
65
|
+
throw new IOException("Invalid output path: " + path);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!parent.exists() && !parent.mkdirs() && !parent.exists()) {
|
|
69
|
+
throw new IOException("Couldn't create dir: " + parent);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (file.exists() && file.isDirectory()) {
|
|
73
|
+
throw new IOException("Output path is a directory: " + file);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!file.exists() && !file.createNewFile() && !file.exists()) {
|
|
77
|
+
throw new IOException("Couldn't create file: " + file);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return file;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Override
|
|
84
|
+
public MediaType contentType() {
|
|
85
|
+
return originalBody.contentType();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@Override
|
|
89
|
+
public long contentLength() {
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
*
|
|
93
|
+
* Okio buffer issue in current version seems to be fixed in the latest versions
|
|
94
|
+
*
|
|
95
|
+
* limiting this was causing the download progress to stop at 2GB size but files still was downloading
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
// if (originalBody.contentLength() > Integer.MAX_VALUE) {
|
|
100
|
+
// This is a workaround for a bug Okio buffer where it can't handle larger than int.
|
|
101
|
+
// return Integer.MAX_VALUE;
|
|
102
|
+
// }
|
|
103
|
+
return originalBody.contentLength();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public boolean isDownloadComplete() {
|
|
107
|
+
return (bytesDownloaded == contentLength()) // Case of non-chunked downloads
|
|
108
|
+
|| (contentLength() == -1 && isEndMarkerReceived); // Case of chunked downloads
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Override
|
|
112
|
+
public BufferedSource source() {
|
|
113
|
+
ProgressReportingSource countable = new ProgressReportingSource();
|
|
114
|
+
return Okio.buffer(countable);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private class ProgressReportingSource implements Source {
|
|
118
|
+
@Override
|
|
119
|
+
public long read(@NonNull Buffer sink, long byteCount) throws IOException {
|
|
120
|
+
try {
|
|
121
|
+
byte[] bytes = new byte[(int) byteCount];
|
|
122
|
+
long read = originalBody.byteStream().read(bytes, 0, (int) byteCount);
|
|
123
|
+
bytesDownloaded += read > 0 ? read : 0;
|
|
124
|
+
if (read > 0) {
|
|
125
|
+
ofStream.write(bytes, 0, (int) read);
|
|
126
|
+
} else if (contentLength() == -1 && read == -1) {
|
|
127
|
+
// End marker has been received for chunked download
|
|
128
|
+
isEndMarkerReceived = true;
|
|
129
|
+
}
|
|
130
|
+
ReactNativeBlobUtilProgressConfig reportConfig = ReactNativeBlobUtilReq.getReportProgress(mTaskId);
|
|
131
|
+
|
|
132
|
+
if (contentLength() != 0) {
|
|
133
|
+
|
|
134
|
+
// For non-chunked download, progress is received / total
|
|
135
|
+
// For chunked download, progress can be either 0 (started) or 1 (ended)
|
|
136
|
+
float progress = (contentLength() != -1) ? bytesDownloaded / contentLength() : ((isEndMarkerReceived) ? 1 : 0);
|
|
137
|
+
|
|
138
|
+
if (reportConfig != null && reportConfig.shouldReport(progress /* progress */)) {
|
|
139
|
+
if (contentLength() != -1) {
|
|
140
|
+
// For non-chunked downloads
|
|
141
|
+
reportProgress(mTaskId, bytesDownloaded, contentLength());
|
|
142
|
+
} else {
|
|
143
|
+
// For chunked downloads
|
|
144
|
+
if (!isEndMarkerReceived) {
|
|
145
|
+
reportProgress(mTaskId, 0, contentLength());
|
|
146
|
+
} else {
|
|
147
|
+
reportProgress(mTaskId, bytesDownloaded, bytesDownloaded);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return read;
|
|
155
|
+
} catch (IOException ex) {
|
|
156
|
+
throw ex;
|
|
157
|
+
} catch (Exception ex) {
|
|
158
|
+
throw new IOException(ex);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private void reportProgress(String taskId, long bytesDownloaded, long contentLength) {
|
|
163
|
+
WritableMap args = Arguments.createMap();
|
|
164
|
+
args.putString("taskId", taskId);
|
|
165
|
+
args.putString("written", String.valueOf(bytesDownloaded));
|
|
166
|
+
args.putString("total", String.valueOf(contentLength));
|
|
167
|
+
rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
|
168
|
+
.emit(ReactNativeBlobUtilConst.EVENT_PROGRESS, args);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@Override
|
|
172
|
+
public Timeout timeout() {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@Override
|
|
177
|
+
public void close() throws IOException {
|
|
178
|
+
ofStream.close();
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
}
|