Skip to content

Commit 4fea693

Browse files
Ron RadtkeRon Radtke
authored andcommitted
Merge remote-tracking branch 'origin/master' into feature/rename
# Conflicts: # windows/ReactNativeBlobUtil/ReactNativeBlobUtil.cpp # windows/ReactNativeBlobUtil/ReactNativeBlobUtil.h
2 parents cb59e13 + a6dcaaf commit 4fea693

File tree

5 files changed

+197
-82
lines changed

5 files changed

+197
-82
lines changed

.eslintrc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
/* See all the pre-defined configs here: https://www.npmjs.com/package/eslint-config-defaults */
3+
"extends": "defaults/configurations/eslint",
4+
"parser": "babel-eslint",
5+
"plugins": [
6+
"react", "html"
7+
],
8+
"env": {
9+
"amd": true,
10+
"browser": true,
11+
"jquery": true,
12+
"node": true,
13+
"es6": false,
14+
"worker": true
15+
},
16+
"rules": {
17+
18+
"eqeqeq": 2,
19+
"comma-dangle": 1,
20+
"no-console": 1,
21+
"no-debugger": 1,
22+
"no-extra-semi": 2,
23+
"no-extra-parens": 1,
24+
"no-extra-boolean-cast": 0,
25+
"no-cond-assign": 2,
26+
"no-irregular-whitespace": 2,
27+
"no-undef": 0,
28+
"no-unused-vars": 0,
29+
"semi": 2,
30+
"semi-spacing": 2,
31+
"valid-jsdoc": [
32+
1,
33+
{ "requireReturn": false,
34+
"requireParamDescription": false,
35+
"requireReturnDescription": false}
36+
],
37+
38+
"react/display-name": 2,
39+
"react/forbid-prop-types": 1,
40+
"react/jsx-boolean-value": 1,
41+
"react/jsx-closing-bracket-location": 1,
42+
"react/jsx-curly-spacing": 1,
43+
"react/jsx-indent-props": 0,
44+
"react/jsx-max-props-per-line": 0,
45+
"react/jsx-no-duplicate-props": 1,
46+
"react/jsx-no-literals": 0,
47+
"react/jsx-no-undef": 1,
48+
"react/jsx-sort-props": 0,
49+
"react/jsx-uses-react": 1,
50+
"react/jsx-uses-vars": 1,
51+
"react/jsx-wrap-multilines": 1,
52+
"react/no-danger": 1,
53+
"react/no-did-mount-set-state": 1,
54+
"react/no-did-update-set-state": 1,
55+
"react/no-direct-mutation-state": 1,
56+
"react/no-multi-comp": 1,
57+
"react/no-set-state": 0,
58+
"react/no-unknown-property": 1,
59+
"react/prop-types": 0,
60+
"react/react-in-jsx-scope": 0,
61+
"react/self-closing-comp": 1,
62+
"react/sort-comp": 1
63+
}
64+
}

package.json

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
{
2-
"name": "react-native-blob-util",
3-
"version": "0.13.2",
4-
"description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.",
5-
"main": "index.js",
6-
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
8-
},
9-
"dependencies": {
10-
"base-64": "0.1.0",
11-
"glob": "^7.1.6"
12-
},
13-
"keywords": [
14-
"react-native",
15-
"fetch",
16-
"blob",
17-
"fs",
18-
"upload",
19-
"file",
20-
"download",
21-
"filestream",
22-
"image header"
23-
],
24-
"repository": {
25-
"url": "https://github.com/RonRadtke/react-native-blob-util"
26-
},
27-
"author": "RonRadtke",
28-
"license": "MIT",
29-
"contributors": [
30-
"Traviskn <>",
31-
32-
"wkh237 <[email protected]>"
33-
]
2+
"name": "react-native-blob-util",
3+
"version": "0.13.4",
4+
"description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"dependencies": {
10+
"base-64": "0.1.0",
11+
"glob": "^7.1.6"
12+
},
13+
"keywords": [
14+
"react-native",
15+
"fetch",
16+
"blob",
17+
"fs",
18+
"upload",
19+
"file",
20+
"download",
21+
"filestream",
22+
"image header"
23+
],
24+
"repository": {
25+
"url": "https://github.com/RonRadtke/react-native-blob-util"
26+
},
27+
"author": "RonRadtke",
28+
"license": "MIT",
29+
"contributors": [
30+
"Traviskn <>",
31+
32+
"wkh237 <[email protected]>"
33+
]
3434
}
File renamed without changes.

windows/ReactNativeBlobUtil/ReactNativeBlobUtil.cpp

Lines changed: 98 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,11 @@ catch (...)
10441044
}
10451045

10461046

1047-
winrt::fire_and_forget ReactNativeBlobUtil::fetchBlob(
1047+
IAsyncAction setTimeout(std::chrono::seconds time) {
1048+
co_await time;
1049+
}
1050+
1051+
winrt::fire_and_forget RNFetchBlob::fetchBlob(
10481052
winrt::Microsoft::ReactNative::JSValueObject options,
10491053
std::string taskId,
10501054
std::string method,
@@ -1060,6 +1064,7 @@ winrt::fire_and_forget ReactNativeBlobUtil::fetchBlob(
10601064
{
10611065
filter.IgnorableServerCertificateErrors().Append(Cryptography::Certificates::ChainValidationResult::Untrusted);
10621066
}
1067+
RNFetchBlobState eventState;
10631068

10641069
winrt::Windows::Web::Http::HttpClient httpClient{ filter };
10651070

@@ -1185,12 +1190,39 @@ winrt::fire_and_forget ReactNativeBlobUtil::fetchBlob(
11851190
}
11861191
}
11871192
}
1193+
1194+
std::string error;
1195+
auto cancellationTimer{ setTimeout(config.timeout) };
1196+
cancellationTimer.Completed([weak_this = weak_from_this(), taskId, error](IAsyncAction const& action, AsyncStatus status) {
1197+
if (status == AsyncStatus::Completed) {
1198+
auto strong_this{ weak_this.lock() };
1199+
if (strong_this) {
1200+
strong_this->m_tasks.Cancel(taskId);
1201+
{
1202+
std::scoped_lock lock{ strong_this->m_mutex };
1203+
strong_this->uploadProgressMap.extract(taskId);
1204+
strong_this->downloadProgressMap.extract(taskId);
1205+
}
1206+
}
1207+
}
1208+
});
1209+
try {
1210+
co_await m_tasks.Add(taskId, ProcessRequestAsync(taskId, filter, requestMessage, config, callback, error));
1211+
}
1212+
catch (...) {
1213+
1214+
}
1215+
if (!error.empty()) {
1216+
if (cancellationTimer.Status() != AsyncStatus::Completed) {
1217+
callback(error, "error", "");
1218+
}
1219+
else {
1220+
callback("RNFetchBlob request timed out", "error", "");
1221+
}
1222+
}
11881223

1189-
ReactNativeBlobUtilState eventState;
1190-
1191-
co_await m_tasks.Add(taskId, ProcessRequestAsync(taskId, filter, requestMessage, config, callback, eventState));
1192-
1193-
m_tasks.Cancel(taskId);
1224+
cancellationTimer.Cancel();
1225+
m_tasks.Cancel(taskId);
11941226
{
11951227
std::scoped_lock lock{ m_mutex };
11961228
uploadProgressMap.extract(taskId);
@@ -1212,14 +1244,7 @@ winrt::fire_and_forget ReactNativeBlobUtil::fetchBlobForm(
12121244

12131245
ReactNativeBlobUtilConfig config{ options };
12141246

1215-
if (config.followRedirect == true)
1216-
{
1217-
filter.AllowAutoRedirect(true);
1218-
}
1219-
else
1220-
{
1221-
filter.AllowAutoRedirect(false);
1222-
}
1247+
filter.AllowAutoRedirect(false);
12231248

12241249
if (config.trusty)
12251250
{
@@ -1375,25 +1400,38 @@ winrt::fire_and_forget ReactNativeBlobUtil::fetchBlobForm(
13751400
}
13761401
}
13771402
}
1378-
1379-
// TODO, set a timeout for cancellation
1380-
1381-
//Create EVENT_STATE_CHANGE
1382-
/*
1383-
taskId, // DO NOT STORE
1384-
@"state": @"2", // store
1385-
@"headers": headers, // store
1386-
@"redirects": redirects, //check how to track
1387-
@"respType" : respType, // store
1388-
@"timeout" : @NO, // do not store
1389-
@"status": [NSNumber numberWithInteger:statusCode] // store
1390-
*/
13911403

1392-
ReactNativeBlobUtilState eventState;
1393-
1394-
co_await m_tasks.Add(taskId, ProcessRequestAsync(taskId, filter, requestMessage, config, callback, eventState));
1404+
std::string error;
1405+
auto cancellationTimer{ setTimeout(config.timeout) };
1406+
cancellationTimer.Completed([weak_this = weak_from_this(), taskId, error](IAsyncAction const& action, AsyncStatus status) {
1407+
if (status == AsyncStatus::Completed) {
1408+
auto strong_this{ weak_this.lock() };
1409+
if (strong_this) {
1410+
strong_this->m_tasks.Cancel(taskId);
1411+
{
1412+
std::scoped_lock lock{ strong_this->m_mutex };
1413+
strong_this->uploadProgressMap.extract(taskId);
1414+
strong_this->downloadProgressMap.extract(taskId);
1415+
}
1416+
}
1417+
}
1418+
});
1419+
try {
1420+
co_await m_tasks.Add(taskId, ProcessRequestAsync(taskId, filter, requestMessage, config, callback, error));
1421+
}
1422+
catch (...) {
13951423

1424+
}
1425+
if (!error.empty()) {
1426+
if (cancellationTimer.Status() != AsyncStatus::Completed) {
1427+
callback(error, "error", "");
1428+
}
1429+
else {
1430+
callback("ReactNativeBlobUtil request timed out", "error", "");
1431+
}
1432+
}
13961433

1434+
cancellationTimer.Cancel();
13971435
m_tasks.Cancel(taskId);
13981436
{
13991437
std::scoped_lock lock{ m_mutex };
@@ -1494,24 +1532,49 @@ winrt::Windows::Foundation::IAsyncAction ReactNativeBlobUtil::ProcessRequestAsyn
14941532
winrt::Windows::Web::Http::HttpRequestMessage& httpRequestMessage,
14951533
ReactNativeBlobUtilConfig& config,
14961534
std::function<void(std::string, std::string, std::string)> callback,
1497-
ReactNativeBlobUtilState& eventState) noexcept
1535+
std::string& error) noexcept
14981536
try
14991537
{
15001538
winrt::Windows::Web::Http::HttpClient httpClient{filter};
1501-
1539+
15021540
winrt::Windows::Web::Http::HttpResponseMessage response{ co_await httpClient.SendRequestAsync(httpRequestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead) };
15031541

1542+
RNFetchBlobState eventState;
1543+
15041544
auto status{ static_cast<int>(response.StatusCode()) };
15051545
if (config.followRedirect) {
15061546
while (status >= 300 && status < 400) {
15071547
auto redirect{ response.Headers().Location().ToString() };
1508-
eventState.redirects.push_back(winrt::to_string(redirect));
1548+
eventState.redirects.push_back(Microsoft::ReactNative::JSValue(winrt::to_string(redirect)));
15091549
httpRequestMessage.RequestUri(Uri{ redirect });
15101550
response = co_await httpClient.SendRequestAsync(httpRequestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead);
15111551
status = static_cast<int>(response.StatusCode());
15121552
}
15131553
}
15141554

1555+
eventState.status = static_cast<int>(response.StatusCode());
1556+
1557+
for (const auto header : response.Content().Headers().GetView()) {
1558+
eventState.headers[winrt::to_string(header.Key())] = winrt::to_string(header.Value());
1559+
}
1560+
1561+
if (response.Content().Headers().ContentType() != nullptr) {
1562+
eventState.respType = winrt::to_string(response.Content().Headers().ContentType().ToString());
1563+
}
1564+
1565+
eventState.state = winrt::to_string(response.ReasonPhrase());
1566+
1567+
m_reactContext.CallJSFunction(L"RCTDeviceEventEmitter", L"emit", L"RNFetchBlobState",
1568+
Microsoft::ReactNative::JSValueObject{
1569+
{ "taskId", taskId },
1570+
{ "state", eventState.state },
1571+
{ "headers", std::move(eventState.headers) },
1572+
{ "redirects", std::move(eventState.redirects) },
1573+
{ "respType", eventState.respType },
1574+
{ "status", eventState.status },
1575+
{ "timeout", false },
1576+
});
1577+
15151578
IReference<uint64_t> contentLength{ response.Content().Headers().ContentLength() };
15161579

15171580
IOutputStream outputStream;
@@ -1604,30 +1667,18 @@ try
16041667
}
16051668
}
16061669
}
1607-
1608-
eventState.status = static_cast<int>(response.StatusCode());
1609-
1610-
for (const auto header : response.Content().Headers().GetView()) {
1611-
eventState.headers[winrt::to_string(header.Key())] = winrt::to_string(header.Value());
1612-
}
1613-
1614-
if (response.Content().Headers().ContentType() != nullptr) {
1615-
eventState.respType = winrt::to_string(response.Content().Headers().ContentType().ToString());
1616-
}
1617-
1618-
eventState.state = winrt::to_string(response.ReasonPhrase());
16191670

16201671
if (writeToFile) {
16211672
callback("", "path", config.path);
16221673
}
16231674
else {
16241675
callback("", "result", resultOutput.str());
16251676
}
1626-
// callback("ReactNativeBlobUtil request timed out", "error", "");
16271677
}
16281678
catch (const hresult_error& ex)
16291679
{
1630-
callback(winrt::to_string(ex.message().c_str()), "error", "");
1680+
error = winrt::to_string(ex.message().c_str());
1681+
//callback(winrt::to_string(ex.message().c_str()), "error", "");
16311682
}
16321683
catch (...) {
16331684
co_return;

windows/ReactNativeBlobUtil/ReactNativeBlobUtil.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct ReactNativeBlobUtilState
6060
*/
6161
std::string state;
6262
winrt::Microsoft::ReactNative::JSValueObject headers;
63-
std::vector<std::string> redirects;
63+
winrt::Microsoft::ReactNative::JSValueArray redirects;
6464
std::string respType;
6565
int status = 0;
6666

@@ -112,7 +112,7 @@ struct ReactNativeBlobUtilProgressConfig {
112112

113113

114114
REACT_MODULE(ReactNativeBlobUtil, L"ReactNativeBlobUtil");
115-
struct ReactNativeBlobUtil
115+
struct ReactNativeBlobUtil : std::enable_shared_from_this<ReactNativeBlobUtil>
116116
{
117117
public:
118118
using StreamId = std::string;
@@ -337,7 +337,7 @@ struct ReactNativeBlobUtil
337337
winrt::Windows::Web::Http::HttpRequestMessage& httpRequestMessage,
338338
ReactNativeBlobUtilConfig& config,
339339
std::function<void(std::string, std::string, std::string)> callback,
340-
ReactNativeBlobUtilState& eventState) noexcept;
340+
std::string& error) noexcept;
341341

342342
const std::map<std::string, std::function<CryptographyCore::HashAlgorithmProvider()>> availableHashes{
343343
{"md5", []() { return CryptographyCore::HashAlgorithmProvider::OpenAlgorithm(CryptographyCore::HashAlgorithmNames::Md5()); } },

0 commit comments

Comments
 (0)