Skip to content

Commit 11febcd

Browse files
committed
Implement Slice and initial stream support
1 parent 7897dbc commit 11febcd

File tree

3 files changed

+294
-21
lines changed

3 files changed

+294
-21
lines changed

RNFetchBlobWin/windows/RNFetchBlobWin/RNFetchBlob.cpp

Lines changed: 187 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "pch.h"
22
#include "RNFetchBlob.h"
3-
43
#include <windows.h>
54
#include <winrt/Windows.Security.Cryptography.h>
65
#include <winrt/Windows.Security.Cryptography.Core.h>
@@ -226,7 +225,6 @@ try
226225
{
227226
data.push_back(var.AsInt8());
228227
}
229-
230228
Streams::IBuffer buffer{ CryptographicBuffer::CreateFromByteArray(data) };
231229

232230
winrt::hstring destDirectoryPath, destFileName;
@@ -259,11 +257,77 @@ catch (...)
259257

260258

261259
// writeStream
260+
winrt::fire_and_forget RNFetchBlob::writeStream(
261+
std::string path,
262+
std::string encoding,
263+
bool append,
264+
std::function<void(std::string, std::string, std::string)> callback) noexcept
265+
try
266+
{
267+
winrt::hstring directoryPath, fileName;
268+
splitPath(path, directoryPath, fileName);
269+
StorageFolder folder{ co_await StorageFolder::GetFolderFromPathAsync(directoryPath) };
270+
StorageFile file{ co_await folder.GetFileAsync(fileName) };
271+
272+
Streams::IRandomAccessStream stream{ co_await file.OpenAsync(FileAccessMode::ReadWrite) };
273+
if (append)
274+
{
275+
stream.Seek(UINT64_MAX);
276+
}
277+
EncodingOptions encodingOption;
278+
if (encoding.compare("utf8"))
279+
{
280+
encodingOption = EncodingOptions::UTF8;
281+
}
282+
else if (encoding.compare("base64"))
283+
{
284+
encodingOption = EncodingOptions::BASE64;
285+
}
286+
else if (encoding.compare("ascii"))
287+
{
288+
encodingOption = EncodingOptions::ASCII;
289+
}
290+
else
291+
{
292+
co_return;
293+
}
294+
295+
// Define the length, in bytes, of the buffer.
296+
uint32_t length = 128;
297+
// Generate random data and copy it to a buffer.
298+
IBuffer buffer = Cryptography::CryptographicBuffer::GenerateRandom(length);
299+
// Encode the buffer to a hexadecimal string (for display).
300+
std::string stringId = winrt::to_string(Cryptography::CryptographicBuffer::EncodeToHexString(buffer));
262301

302+
RNFetchBlobStream streamInstance{ stream, append, encodingOption };
263303

264304

305+
306+
}
307+
catch (const hresult_error& ex)
308+
{
309+
callback("EUNSPECIFIED", "Failed to create write stream at path `" + path + "`; " + winrt::to_string(ex.message().c_str()), "");
310+
}
311+
312+
313+
// writeChunk
314+
void RNFetchBlob::writeChunk(
315+
std::string streamId,
316+
std::string data,
317+
std::function<void(std::string)> callback) noexcept
318+
{
319+
}
320+
265321
// readStream
322+
void RNFetchBlob::readStream(
323+
std::string path,
324+
std::string encoding,
325+
int bufferSize,
326+
int tick,
327+
const std::string streamId) noexcept
328+
{
266329

330+
}
267331

268332

269333
// mkdir - Implemented, not tested
@@ -638,7 +702,6 @@ catch (const hresult_error& ex)
638702
}
639703

640704

641-
642705
// df - Implemented, not tested
643706
winrt::fire_and_forget RNFetchBlob::df(
644707
std::function<void(std::string, winrt::Microsoft::ReactNative::JSValueObject&)> callback) noexcept
@@ -658,11 +721,131 @@ catch (...)
658721
callback("Failed to get storage usage.", emptyObject);
659722
}
660723

724+
725+
winrt::fire_and_forget RNFetchBlob::slice(
726+
std::string src,
727+
std::string dest,
728+
uint32_t start,
729+
uint32_t end,
730+
winrt::Microsoft::ReactNative::ReactPromise<std::string> promise) noexcept
731+
try
732+
{
733+
winrt::hstring srcDirectoryPath, srcFileName, destDirectoryPath, destFileName;
734+
splitPath(src, srcDirectoryPath, srcFileName);
735+
splitPath(src, destDirectoryPath, destFileName);
736+
737+
StorageFolder srcFolder{ co_await StorageFolder::GetFolderFromPathAsync(srcDirectoryPath) };
738+
StorageFolder destFolder{ co_await StorageFolder::GetFolderFromPathAsync(destDirectoryPath) };
739+
740+
StorageFile srcFile{ co_await srcFolder.GetFileAsync(srcFileName) };
741+
StorageFile destFile{ co_await destFolder.CreateFileAsync(destFileName, CreationCollisionOption::OpenIfExists) };
742+
743+
uint32_t length{ end - start };
744+
Streams::IBuffer buffer;
745+
Streams::IRandomAccessStream stream{ co_await srcFile.OpenAsync(FileAccessMode::Read) };
746+
stream.Seek(start);
747+
stream.ReadAsync(buffer, length, Streams::InputStreamOptions::None);
748+
co_await FileIO::WriteBufferAsync(destFile, buffer);
749+
750+
promise.Resolve(dest);
751+
}
752+
catch (...)
753+
{
754+
promise.Reject("Unable to slice file");
755+
}
756+
757+
758+
void RNFetchBlob::fetchBlob(
759+
winrt::Microsoft::ReactNative::JSValueObject options,
760+
std::string taskId,
761+
std::string method,
762+
std::string url,
763+
winrt::Microsoft::ReactNative::JSValueObject headers,
764+
std::string body,
765+
std::function<void(std::string)> callback) noexcept
766+
{
767+
768+
}
769+
770+
void RNFetchBlob::fetchBlobForm(
771+
winrt::Microsoft::ReactNative::JSValueObject options,
772+
std::string taskId,
773+
std::string method,
774+
std::string url,
775+
winrt::Microsoft::ReactNative::JSValueObject headers,
776+
winrt::Microsoft::ReactNative::JSValueArray body,
777+
std::function<void(std::string)> callback) noexcept
778+
{
779+
780+
}
781+
782+
void RNFetchBlob::enableProgressReport(
783+
std::string taskId,
784+
int interval,
785+
int count) noexcept
786+
{
787+
}
788+
789+
// enableUploadProgressReport
790+
void RNFetchBlob::enableUploadProgressReport(
791+
std::string taskId,
792+
int interval,
793+
int count) noexcept
794+
{
795+
}
796+
797+
// cancelRequest
798+
void RNFetchBlob::cancelRequest(
799+
std::string taskId,
800+
std::function<void(std::string)> callback) noexcept
801+
{
802+
}
803+
804+
void RNFetchBlob::removeSession(
805+
winrt::Microsoft::ReactNative::JSValueObject paths,
806+
std::function<void(std::string)> callback) noexcept
807+
{
808+
809+
}
810+
811+
void RNFetchBlob::closeStream(
812+
std::string streamId,
813+
std::function<void(std::string)> callback) noexcept
814+
{
815+
816+
}
817+
818+
661819
void RNFetchBlob::splitPath(const std::string& fullPath, winrt::hstring& directoryPath, winrt::hstring& fileName) noexcept
662820
{
663-
std::filesystem::path path(fullPath);
821+
std::filesystem::path path{ fullPath };
664822
path.make_preferred();
665823

666824
directoryPath = path.has_parent_path() ? winrt::to_hstring(path.parent_path().c_str()) : L"";
667825
fileName = path.has_filename() ? winrt::to_hstring(path.filename().c_str()) : L"";
668826
}
827+
828+
829+
830+
RNFetchBlobStream::RNFetchBlobStream(Streams::IRandomAccessStream & _streamInstance, bool _append, EncodingOptions _encoding) noexcept
831+
: streamInstance{ std::move(_streamInstance) }
832+
, append{ _append }
833+
, encoding{ _encoding }
834+
{
835+
}
836+
837+
838+
void RNFetchBlobStreamMap::Add(StreamId streamId, RNFetchBlobStream streamContainer) noexcept
839+
{
840+
m_streamMap.try_emplace(streamId, streamContainer);
841+
}
842+
RNFetchBlobStream& RNFetchBlobStreamMap::Get(StreamId streamId) noexcept
843+
{
844+
auto iter{ m_streamMap.find(streamId) };
845+
return iter->second;
846+
}
847+
void RNFetchBlobStreamMap::Remove(StreamId streamId) noexcept
848+
{
849+
m_streamMap.extract(streamId);
850+
}
851+

RNFetchBlobWin/windows/RNFetchBlobWin/RNFetchBlob.h

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,39 @@
33
#include <winrt/Windows.Foundation.h>
44
#include <winrt/Windows.Security.Cryptography.h>
55
#include <winrt/Windows.Security.Cryptography.Core.h>
6+
#include <mutex>
67

78
namespace Cryptography = winrt::Windows::Security::Cryptography;
89
namespace CryptographyCore = winrt::Windows::Security::Cryptography::Core;
910

11+
enum struct EncodingOptions { UTF8 , BASE64, ASCII, URI};
12+
13+
struct RNFetchBlobStream
14+
{
15+
public:
16+
RNFetchBlobStream::RNFetchBlobStream(winrt::Windows::Storage::Streams::IRandomAccessStream& _streamInstance, bool _append, EncodingOptions _encoding) noexcept;
17+
18+
winrt::Windows::Storage::Streams::IRandomAccessStream streamInstance;
19+
const bool append;
20+
const EncodingOptions encoding;
21+
};
22+
23+
struct RNFetchBlobStreamMap
24+
{
25+
public:
26+
using StreamId = std::string;
27+
RNFetchBlobStreamMap() = default;
28+
~RNFetchBlobStreamMap() = default;
29+
void Add(StreamId streamId, RNFetchBlobStream streamContainer) noexcept;
30+
RNFetchBlobStream& Get(StreamId streamId) noexcept;
31+
void Remove(StreamId streamId) noexcept;
32+
33+
private:
34+
std::mutex m_mutex;
35+
std::map<StreamId, RNFetchBlobStream> m_streamMap;
36+
};
37+
38+
1039
REACT_MODULE(RNFetchBlob, L"RNFetchBlob");
1140
struct RNFetchBlob
1241
{
@@ -31,7 +60,7 @@ struct RNFetchBlob
3160
winrt::Microsoft::ReactNative::JSValueArray dataArray,
3261
winrt::Microsoft::ReactNative::ReactPromise<std::string> promise) noexcept;
3362

34-
63+
3564
// writeFile
3665
REACT_METHOD(writeFile);
3766
winrt::fire_and_forget writeFile(
@@ -48,13 +77,29 @@ struct RNFetchBlob
4877
bool append,
4978
winrt::Microsoft::ReactNative::ReactPromise<int> promise) noexcept;
5079

51-
5280
// writeStream
81+
REACT_METHOD(writeStream);
82+
winrt::fire_and_forget RNFetchBlob::writeStream(
83+
std::string path,
84+
std::string encoding,
85+
bool append,
86+
std::function<void(std::string, std::string, std::string)> callback) noexcept;
5387

54-
88+
// writeChunk
89+
REACT_METHOD(writeChunk);
90+
void RNFetchBlob::writeChunk(
91+
std::string streamId,
92+
std::string data,
93+
std::function<void(std::string)> callback) noexcept;
5594

5695
// readStream
57-
96+
REACT_METHOD(readStream);
97+
void RNFetchBlob::readStream(
98+
std::string path,
99+
std::string encoding,
100+
int bufferSize,
101+
int tick,
102+
const std::string streamId) noexcept;
58103

59104

60105
// mkdir
@@ -78,7 +123,7 @@ struct RNFetchBlob
78123
std::string path,
79124
std::string algorithm,
80125
winrt::Microsoft::ReactNative::ReactPromise<std::string> promise) noexcept;
81-
126+
82127
// ls
83128
REACT_METHOD(ls);
84129
winrt::fire_and_forget ls(
@@ -142,8 +187,64 @@ struct RNFetchBlob
142187
winrt::fire_and_forget df(
143188
std::function<void(std::string, winrt::Microsoft::ReactNative::JSValueObject&)> callback) noexcept;
144189

190+
REACT_METHOD(slice);
191+
winrt::fire_and_forget RNFetchBlob::slice(
192+
std::string src,
193+
std::string dest,
194+
uint32_t start,
195+
uint32_t end,
196+
winrt::Microsoft::ReactNative::ReactPromise<std::string> promise) noexcept;
197+
198+
REACT_METHOD(fetchBlob);
199+
void fetchBlob(
200+
winrt::Microsoft::ReactNative::JSValueObject options,
201+
std::string taskId,
202+
std::string method,
203+
std::string url,
204+
winrt::Microsoft::ReactNative::JSValueObject headers,
205+
std::string body,
206+
std::function<void(std::string)> callback) noexcept;
207+
208+
REACT_METHOD(fetchBlobForm);
209+
void fetchBlobForm(
210+
winrt::Microsoft::ReactNative::JSValueObject options,
211+
std::string taskId,
212+
std::string method,
213+
std::string url,
214+
winrt::Microsoft::ReactNative::JSValueObject headers,
215+
winrt::Microsoft::ReactNative::JSValueArray body,
216+
std::function<void(std::string)> callback) noexcept;
217+
218+
REACT_METHOD(enableProgressReport);
219+
void enableProgressReport(
220+
std::string taskId,
221+
int interval,
222+
int count) noexcept;
223+
224+
// enableUploadProgressReport
225+
REACT_METHOD(enableUploadProgressReport);
226+
void enableUploadProgressReport(
227+
std::string taskId,
228+
int interval,
229+
int count) noexcept;
230+
231+
// cancelRequest
232+
REACT_METHOD(cancelRequest);
233+
void cancelRequest(
234+
std::string taskId,
235+
std::function<void(std::string)> callback) noexcept;
236+
237+
REACT_METHOD(removeSession);
238+
void removeSession(
239+
winrt::Microsoft::ReactNative::JSValueObject paths,
240+
std::function<void(std::string)> callback) noexcept;
241+
242+
REACT_METHOD(closeStream);
243+
void closeStream(
244+
std::string streamId,
245+
std::function<void(std::string)> callback) noexcept;
145246

146-
// Helper methods
247+
// Helper methods
147248
private:
148249
constexpr static int64_t UNIX_EPOCH_IN_WINRT_SECONDS = 11644473600;
149250

0 commit comments

Comments
 (0)