@@ -131,7 +131,7 @@ RNFetchBlobConfig::RNFetchBlobConfig(winrt::Microsoft::ReactNative::JSValueObjec
131131 bool hasTrailingSlash{ filepath[fileLength - 1 ] == ' \\ ' || filepath[fileLength - 1 ] == ' /' };
132132 std::filesystem::path pathToParse{ hasTrailingSlash ? filepath.substr (0 , fileLength - 1 ) : filepath };
133133 pathToParse.make_preferred ();
134- path = winrt::to_string ( pathToParse.c_str () );
134+ path = pathToParse.string ( );
135135 }
136136 trusty = options[" trusty" ].AsBoolean ();
137137
230230 }
231231 catch (...)
232232 {
233- promise.Reject (" EEXIST: File already exists. " ); // TODO: Include filepath
233+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EEXIST" , " EEXIST : File already exists; " + path });
234234 shouldExit = true ;
235235 }
236236 }
@@ -245,13 +245,11 @@ catch (const hresult_error& ex)
245245 hresult result{ ex.code () };
246246 if (result == 0x80070002 ) // FileNotFoundException
247247 {
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 });
249249 }
250250 else
251251 {
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 });
255253 }
256254}
257255
@@ -286,16 +284,15 @@ catch (const hresult_error& ex)
286284 hresult result{ ex.code () };
287285 if (result == 0x80070002 ) // FileNotFoundException
288286 {
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 });
290288 }
291289 else if (result == 0x80070050 )
292290 {
293- promise.Reject (" EEXIST: File already exists. " );
291+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EEXIST" , " EEXIST : File already exists; " + path } );
294292 }
295293 else
296294 {
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 ()) });
299296 }
300297}
301298
353350 co_await stream.WriteAsync (buffer);
354351 promise.Resolve (buffer.Length ());
355352}
356- catch (... )
353+ catch (const hresult_error& ex )
357354{
358- promise.Reject (" Failed to write " );
355+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EUNSPECIFIED " , " EUNSPECIFIED: " + winrt::to_string (ex. message ()) + " ; " + path } );
359356}
360357
361358winrt::fire_and_forget RNFetchBlob::writeFileArray (
@@ -396,9 +393,9 @@ winrt::fire_and_forget RNFetchBlob::writeFileArray(
396393
397394 co_return ;
398395}
399- catch (... )
396+ catch (const hresult_error& ex )
400397{
401- promise.Reject (" Failed to write " );
398+ promise.Reject (winrt::Microsoft::ReactNative::ReactError{ " EUNSPECIFIED " , " EUNSPECIFIED: " + winrt::to_string (ex. message ()) + " ; " + path } );
402399}
403400
404401
@@ -1058,15 +1055,7 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
10581055{
10591056 winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
10601057 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 );
10701059 if (config.trusty )
10711060 {
10721061 filter.IgnorableServerCertificateErrors ().Append (Cryptography::Certificates::ChainValidationResult::Untrusted);
@@ -1197,7 +1186,10 @@ winrt::fire_and_forget RNFetchBlob::fetchBlob(
11971186 }
11981187 }
11991188
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+
12011193 m_tasks.Cancel (taskId);
12021194 {
12031195 std::scoped_lock lock{ m_mutex };
@@ -1215,8 +1207,6 @@ winrt::fire_and_forget RNFetchBlob::fetchBlobForm(
12151207 winrt::Microsoft::ReactNative::JSValueArray body,
12161208 std::function<void (std::string, std::string, std::string)> callback) noexcept
12171209{
1218- // createBlobForm(options, taskId, method, url, headers, "", body, callback);
1219- // co_return;
12201210 winrt::hstring boundary{ L" -----" };
12211211 winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter filter;
12221212
@@ -1387,7 +1377,23 @@ winrt::fire_and_forget RNFetchBlob::fetchBlobForm(
13871377 }
13881378
13891379 // 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+
13911397 m_tasks.Cancel (taskId);
13921398 {
13931399 std::scoped_lock lock{ m_mutex };
@@ -1487,19 +1493,32 @@ winrt::Windows::Foundation::IAsyncAction RNFetchBlob::ProcessRequestAsync(
14871493 const winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter& filter,
14881494 winrt::Windows::Web::Http::HttpRequestMessage& httpRequestMessage,
14891495 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
14911498try
14921499{
14931500 winrt::Windows::Web::Http::HttpClient httpClient{filter};
14941501
14951502 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+
14961515 IReference<uint64_t > contentLength{ response.Content ().Headers ().ContentLength () };
14971516
14981517 IOutputStream outputStream;
1518+ bool writeToFile{ config.fileCache || !config.path .empty () };
14991519
1500- if (config. fileCache )
1520+ if (writeToFile )
15011521 {
1502-
15031522 if (config.path .empty ())
15041523 {
15051524 config.path = winrt::to_string (ApplicationData::Current ().TemporaryFolder ().Path ()) + " \\ RNFetchBlobTmp_" + taskId;
@@ -1508,7 +1527,6 @@ try
15081527 config.path += " ." + config.appendExt ;
15091528 }
15101529 }
1511-
15121530 std::filesystem::path path{ config.path };
15131531 StorageFolder storageFolder{ co_await StorageFolder::GetFolderFromPathAsync ( path.parent_path ().wstring ()) };
15141532 StorageFile storageFile{ co_await storageFolder.CreateFileAsync (path.filename ().wstring (), CreationCollisionOption::FailIfExists) };
@@ -1546,7 +1564,6 @@ try
15461564 buffer.Length (0 );
15471565 auto readBuffer{ co_await contentStream.ReadAsync (buffer, buffer.Capacity (), InputStreamOptions::None) };
15481566
1549- //
15501567 read += readBuffer.Length ();
15511568 totalRead += read;
15521569
@@ -1557,7 +1574,7 @@ try
15571574
15581575 readContents = winrt::to_string (CryptographicBuffer::EncodeToBase64String (readBuffer));
15591576
1560- if (config. fileCache ) {
1577+ if (writeToFile ) {
15611578 co_await outputStream.WriteAsync (readBuffer);
15621579 }
15631580 else {
@@ -1587,8 +1604,20 @@ try
15871604 }
15881605 }
15891606 }
1607+
1608+ eventState.status = static_cast <int >(response.StatusCode ());
15901609
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) {
15921621 callback (" " , " path" , config.path );
15931622 }
15941623 else {
@@ -1600,6 +1629,9 @@ catch (const hresult_error& ex)
16001629{
16011630 callback (winrt::to_string (ex.message ().c_str ()), " error" , " " );
16021631}
1632+ catch (...) {
1633+ co_return ;
1634+ }
16031635
16041636
16051637RNFetchBlobStream::RNFetchBlobStream (Streams::IRandomAccessStream& _streamInstance, EncodingOptions _encoding) noexcept
0 commit comments