@@ -131,7 +131,7 @@ RNFetchBlobConfig::RNFetchBlobConfig(winrt::Microsoft::ReactNative::JSValueObjec
131
131
bool hasTrailingSlash{ filepath[fileLength - 1 ] == ' \\ ' || filepath[fileLength - 1 ] == ' /' };
132
132
std::filesystem::path pathToParse{ hasTrailingSlash ? filepath.substr (0 , fileLength - 1 ) : filepath };
133
133
pathToParse.make_preferred ();
134
- path = winrt::to_string ( pathToParse.c_str () );
134
+ path = pathToParse.string ( );
135
135
}
136
136
trusty = options[" trusty" ].AsBoolean ();
137
137
230
230
}
231
231
catch (...)
232
232
{
233
- promise.Reject (" EEXIST: File already exists. " ); // TODO: Include filepath
233
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EEXIST" , " EEXIST : File already exists; " + path });
234
234
shouldExit = true ;
235
235
}
236
236
}
@@ -245,13 +245,11 @@ catch (const hresult_error& ex)
245
245
hresult result{ ex.code () };
246
246
if (result == 0x80070002 ) // FileNotFoundException
247
247
{
248
- promise.Reject (" ENOENT: File does not exist and could not be created" ); // TODO: Include filepath
248
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " ENOENT" , " ENOENT : File does not exist and could not be created; " + path });
249
249
}
250
250
else
251
251
{
252
- // EUNSPECIFIED: Failed to write to file
253
- auto errorMessage{ L" EUNSPECIFIED: " + ex.message () };
254
- promise.Reject (errorMessage.c_str ());
252
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EUNSPECIFIED" , " EUNSPECIFIED: " + winrt::to_string (ex.message ()) + " ; " + path });
255
253
}
256
254
}
257
255
@@ -286,16 +284,15 @@ catch (const hresult_error& ex)
286
284
hresult result{ ex.code () };
287
285
if (result == 0x80070002 ) // FileNotFoundException
288
286
{
289
- promise.Reject (" ENOENT: File does not exist and could not be created" ); // TODO: Include filepath
287
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " ENOENT" , " ENOENT : File does not exist and could not be created; " + path });
290
288
}
291
289
else if (result == 0x80070050 )
292
290
{
293
- promise.Reject (" EEXIST: File already exists. " );
291
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EEXIST" , " EEXIST : File already exists; " + path } );
294
292
}
295
293
else
296
294
{
297
- auto errorMessage{ L" EUNSPECIFIED: " + ex.message () };
298
- promise.Reject (errorMessage.c_str ());
295
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EUNSPECIFIED" , " EUNSPECIFIED: " + winrt::to_string (ex.message ()) });
299
296
}
300
297
}
301
298
353
350
co_await stream.WriteAsync (buffer);
354
351
promise.Resolve (buffer.Length ());
355
352
}
356
- catch (... )
353
+ catch (const hresult_error& ex )
357
354
{
358
- promise.Reject (" Failed to write " );
355
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EUNSPECIFIED " , " EUNSPECIFIED: " + winrt::to_string (ex. message ()) + " ; " + path } );
359
356
}
360
357
361
358
winrt::fire_and_forget RNFetchBlob::writeFileArray (
@@ -396,9 +393,9 @@ winrt::fire_and_forget RNFetchBlob::writeFileArray(
396
393
397
394
co_return ;
398
395
}
399
- catch (... )
396
+ catch (const hresult_error& ex )
400
397
{
401
- promise.Reject (" Failed to write " );
398
+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EUNSPECIFIED " , " EUNSPECIFIED: " + winrt::to_string (ex. message ()) + " ; " + path } );
402
399
}
403
400
404
401
@@ -1058,15 +1055,7 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
1058
1055
{
1059
1056
winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
1060
1057
RNFetchBlobConfig config{ options };
1061
- if (config.followRedirect == true )
1062
- {
1063
- filter.AllowAutoRedirect (true );
1064
- }
1065
- else
1066
- {
1067
- filter.AllowAutoRedirect (false );
1068
- }
1069
-
1058
+ filter.AllowAutoRedirect (false );
1070
1059
if (config.trusty )
1071
1060
{
1072
1061
filter.IgnorableServerCertificateErrors ().Append (Cryptography::Certificates::ChainValidationResult::Untrusted);
@@ -1197,7 +1186,10 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
1197
1186
}
1198
1187
}
1199
1188
1200
- co_await m_tasks.Add (taskId, ProcessRequestAsync (taskId, filter, requestMessage, config, callback));
1189
+ RNFetchBlobState eventState;
1190
+
1191
+ co_await m_tasks.Add (taskId, ProcessRequestAsync (taskId, filter, requestMessage, config, callback, eventState));
1192
+
1201
1193
m_tasks.Cancel (taskId);
1202
1194
{
1203
1195
std::scoped_lock lock{ m_mutex };
@@ -1215,8 +1207,6 @@ winrt::fire_and_forget RNFetchBlob::fetchBlobForm(
1215
1207
winrt::Microsoft::ReactNative::JSValueArray body,
1216
1208
std::function<void (std::string, std::string, std::string)> callback) noexcept
1217
1209
{
1218
- // createBlobForm(options, taskId, method, url, headers, "", body, callback);
1219
- // co_return;
1220
1210
winrt::hstring boundary{ L" -----" };
1221
1211
winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
1222
1212
@@ -1387,7 +1377,23 @@ winrt::fire_and_forget RNFetchBlob::fetchBlobForm(
1387
1377
}
1388
1378
1389
1379
// TODO, set a timeout for cancellation
1390
- co_await m_tasks.Add (taskId, ProcessRequestAsync (taskId, filter, requestMessage, config, callback));
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
+ */
1391
+
1392
+ RNFetchBlobState eventState;
1393
+
1394
+ co_await m_tasks.Add (taskId, ProcessRequestAsync (taskId, filter, requestMessage, config, callback, eventState));
1395
+
1396
+
1391
1397
m_tasks.Cancel (taskId);
1392
1398
{
1393
1399
std::scoped_lock lock{ m_mutex };
@@ -1487,19 +1493,32 @@ winrt::Windows::Foundation::IAsyncAction RNFetchBlob::ProcessRequestAsync(
1487
1493
const winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter& filter,
1488
1494
winrt::Windows::Web::Http::HttpRequestMessage& httpRequestMessage,
1489
1495
RNFetchBlobConfig& config,
1490
- std::function<void (std::string, std::string, std::string)> callback) noexcept
1496
+ std::function<void (std::string, std::string, std::string)> callback,
1497
+ RNFetchBlobState& eventState) noexcept
1491
1498
try
1492
1499
{
1493
1500
winrt::Windows::Web::Http::HttpClient httpClient{filter};
1494
1501
1495
1502
winrt::Windows::Web::Http::HttpResponseMessage response{ co_await httpClient.SendRequestAsync (httpRequestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead) };
1503
+
1504
+ auto status{ static_cast <int >(response.StatusCode ()) };
1505
+ if (config.followRedirect ) {
1506
+ while (status >= 300 && status < 400 ) {
1507
+ auto redirect{ response.Headers ().Location ().ToString () };
1508
+ eventState.redirects .push_back (winrt::to_string (redirect));
1509
+ httpRequestMessage.RequestUri (Uri{ redirect });
1510
+ response = co_await httpClient.SendRequestAsync (httpRequestMessage, winrt::Windows::Web::Http::HttpCompletionOption::ResponseHeadersRead);
1511
+ status = static_cast <int >(response.StatusCode ());
1512
+ }
1513
+ }
1514
+
1496
1515
IReference<uint64_t > contentLength{ response.Content ().Headers ().ContentLength () };
1497
1516
1498
1517
IOutputStream outputStream;
1518
+ bool writeToFile{ config.fileCache || !config.path .empty () };
1499
1519
1500
- if (config. fileCache )
1520
+ if (writeToFile )
1501
1521
{
1502
-
1503
1522
if (config.path .empty ())
1504
1523
{
1505
1524
config.path = winrt::to_string (ApplicationData::Current ().TemporaryFolder ().Path ()) + " \\ RNFetchBlobTmp_" + taskId;
@@ -1508,7 +1527,6 @@ try
1508
1527
config.path += " ." + config.appendExt ;
1509
1528
}
1510
1529
}
1511
-
1512
1530
std::filesystem::path path{ config.path };
1513
1531
StorageFolder storageFolder{ co_await StorageFolder::GetFolderFromPathAsync ( path.parent_path ().wstring ()) };
1514
1532
StorageFile storageFile{ co_await storageFolder.CreateFileAsync (path.filename ().wstring (), CreationCollisionOption::FailIfExists) };
@@ -1546,7 +1564,6 @@ try
1546
1564
buffer.Length (0 );
1547
1565
auto readBuffer{ co_await contentStream.ReadAsync (buffer, buffer.Capacity (), InputStreamOptions::None) };
1548
1566
1549
- //
1550
1567
read += readBuffer.Length ();
1551
1568
totalRead += read ;
1552
1569
@@ -1557,7 +1574,7 @@ try
1557
1574
1558
1575
readContents = winrt::to_string (CryptographicBuffer::EncodeToBase64String (readBuffer));
1559
1576
1560
- if (config. fileCache ) {
1577
+ if (writeToFile ) {
1561
1578
co_await outputStream.WriteAsync (readBuffer);
1562
1579
}
1563
1580
else {
@@ -1587,8 +1604,20 @@ try
1587
1604
}
1588
1605
}
1589
1606
}
1607
+
1608
+ eventState.status = static_cast <int >(response.StatusCode ());
1590
1609
1591
- if (config.fileCache ) {
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 ());
1619
+
1620
+ if (writeToFile) {
1592
1621
callback (" " , " path" , config.path );
1593
1622
}
1594
1623
else {
@@ -1600,6 +1629,9 @@ catch (const hresult_error& ex)
1600
1629
{
1601
1630
callback (winrt::to_string (ex.message ().c_str ()), " error" , " " );
1602
1631
}
1632
+ catch (...) {
1633
+ co_return ;
1634
+ }
1603
1635
1604
1636
1605
1637
RNFetchBlobStream::RNFetchBlobStream (Streams::IRandomAccessStream& _streamInstance, EncodingOptions _encoding) noexcept
0 commit comments