react-native-blob-util 0.19.0 → 0.19.2

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.
Files changed (91) hide show
  1. package/.eslintrc.js +56 -56
  2. package/LICENSE +21 -21
  3. package/Migration.md +41 -41
  4. package/README.md +1071 -1071
  5. package/android/gradle.properties +1 -1
  6. package/android/proguard-rules.pro +17 -17
  7. package/android/src/main/AndroidManifest.xml +39 -40
  8. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java +57 -57
  9. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConst.java +20 -20
  10. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFS.java +2 -2
  11. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java +9 -9
  12. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilImpl.java +431 -431
  13. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilProgressConfig.java +39 -39
  14. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +972 -968
  15. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilDefaultResp.java +98 -98
  16. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java +157 -157
  17. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/FileDescription.java +19 -19
  18. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/FileProvider.java +4 -4
  19. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/MimeType.java +70 -70
  20. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/PathResolver.java +223 -223
  21. package/android/src/main/java/com/ReactNativeBlobUtil/Utils/Tls12SocketFactory.java +68 -68
  22. package/android/src/main/res/values/strings.xml +3 -3
  23. package/android/src/main/res/xml/provider_paths.xml +12 -12
  24. package/android/src/newarch/java/com/ReactNativeBlobUtil/ReactNativeBlobUtil.java +1 -1
  25. package/android.js +58 -58
  26. package/class/ReactNativeBlobUtilCanceledFetchError.js +9 -9
  27. package/class/ReactNativeBlobUtilFile.js +5 -5
  28. package/class/ReactNativeBlobUtilReadStream.js +84 -84
  29. package/class/ReactNativeBlobUtilSession.js +68 -68
  30. package/class/ReactNativeBlobUtilWriteStream.js +50 -50
  31. package/class/StatefulPromise.js +7 -7
  32. package/codegenSpecs/NativeBlobUtils.js +86 -82
  33. package/components/Fetch.onPress.js +10 -10
  34. package/components/Fetch.when.js +15 -15
  35. package/fetch.js +344 -344
  36. package/fs.js +480 -480
  37. package/index.d.ts +871 -871
  38. package/index.js +64 -64
  39. package/index.js.flow +191 -191
  40. package/index.web.js +1 -1
  41. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.h +55 -55
  42. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.mm +993 -993
  43. package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +403 -403
  44. package/ios/ReactNativeBlobUtilConst.h +58 -58
  45. package/ios/ReactNativeBlobUtilConst.mm +47 -47
  46. package/ios/ReactNativeBlobUtilFS.h +108 -108
  47. package/ios/ReactNativeBlobUtilFS.mm +977 -977
  48. package/ios/ReactNativeBlobUtilFileTransformer.h +23 -23
  49. package/ios/ReactNativeBlobUtilFileTransformer.mm +20 -20
  50. package/ios/ReactNativeBlobUtilNetwork.h +49 -49
  51. package/ios/ReactNativeBlobUtilNetwork.mm +159 -159
  52. package/ios/ReactNativeBlobUtilProgress.h +32 -32
  53. package/ios/ReactNativeBlobUtilProgress.mm +57 -57
  54. package/ios/ReactNativeBlobUtilReqBuilder.h +37 -37
  55. package/ios/ReactNativeBlobUtilReqBuilder.mm +292 -292
  56. package/ios/ReactNativeBlobUtilRequest.h +48 -48
  57. package/ios/ReactNativeBlobUtilRequest.mm +535 -535
  58. package/ios.js +61 -61
  59. package/json-stream.js +42 -42
  60. package/lib/oboe-browser.js +2703 -2703
  61. package/mediacollection.js +36 -36
  62. package/package.json +55 -55
  63. package/polyfill/Blob.js +362 -362
  64. package/polyfill/Event.js +11 -11
  65. package/polyfill/EventTarget.js +78 -78
  66. package/polyfill/Fetch.js +219 -219
  67. package/polyfill/File.js +27 -27
  68. package/polyfill/FileReader.js +91 -91
  69. package/polyfill/ProgressEvent.js +32 -32
  70. package/polyfill/XMLHttpRequest.js +466 -466
  71. package/polyfill/XMLHttpRequestEventTarget.js +126 -126
  72. package/polyfill/index.js +11 -11
  73. package/react-native-blob-util.podspec +45 -45
  74. package/types.js +69 -69
  75. package/utils/log.js +40 -40
  76. package/utils/unicode.js +7 -7
  77. package/utils/uri.js +33 -33
  78. package/utils/uuid.js +4 -4
  79. package/windows/README.md +2 -2
  80. package/windows/ReactNativeBlobUtil/PropertySheet.props +15 -15
  81. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.cpp +1701 -1693
  82. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.def +3 -3
  83. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.h +379 -366
  84. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj +181 -181
  85. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj.filters +31 -31
  86. package/windows/ReactNativeBlobUtil/ReactPackageProvider.cpp +15 -15
  87. package/windows/ReactNativeBlobUtil/ReactPackageProvider.h +20 -20
  88. package/windows/ReactNativeBlobUtil/ReactPackageProvider.idl +9 -9
  89. package/windows/ReactNativeBlobUtil/packages.config +3 -3
  90. package/windows/ReactNativeBlobUtil/pch.cpp +1 -1
  91. package/windows/ReactNativeBlobUtil/pch.h +3 -3
@@ -1,993 +1,993 @@
1
- //
2
- // ReactNativeBlobUtil.m
3
- //
4
- // Created by wkh237 on 2016/4/28.
5
- //
6
-
7
- #import "ReactNativeBlobUtil.h"
8
- #import "ReactNativeBlobUtilFS.h"
9
- #import "ReactNativeBlobUtilNetwork.h"
10
- #import "ReactNativeBlobUtilConst.h"
11
- #import "ReactNativeBlobUtilReqBuilder.h"
12
- #import "ReactNativeBlobUtilProgress.h"
13
-
14
- #if RCT_NEW_ARCH_ENABLED
15
- #import <ReactNativeBlobUtilSpec/ReactNativeBlobUtilSpec.h>
16
- #endif
17
-
18
- dispatch_queue_t commonTaskQueue;
19
- dispatch_queue_t fsQueue;
20
-
21
- ////////////////////////////////////////
22
- //
23
- // Exported native methods
24
- //
25
- ////////////////////////////////////////
26
-
27
- #pragma mark ReactNativeBlobUtil exported methods
28
-
29
- @implementation ReactNativeBlobUtil
30
-
31
- @synthesize filePathPrefix;
32
- @synthesize documentController;
33
- @synthesize bridge;
34
- static bool hasListeners = NO;
35
-
36
- - (NSArray<NSString*> *)supportedEvents {
37
- return @[@"ReactNativeBlobUtilState", @"ReactNativeBlobUtilServerPush", @"ReactNativeBlobUtilProgress", @"ReactNativeBlobUtilProgress-upload", @"ReactNativeBlobUtilExpire", @"ReactNativeBlobUtilMessage", @"ReactNativeBlobUtilFilesystem", @"log", @"warn", @"error", @"data", @"end", @"reportProgress", @"reportUploadProgress"];
38
- }
39
-
40
- // Will be called when this module's first listener is added.
41
- -(void)startObserving {
42
- hasListeners = YES;
43
- // Set up any upstream listeners or background tasks as necessary
44
- }
45
-
46
- // Will be called when this module's last listener is removed, or on dealloc.
47
- -(void)stopObserving {
48
- hasListeners = NO;
49
- // Remove upstream listeners, stop unnecessary background tasks
50
- }
51
-
52
- - (void)emitEvent:(NSString *)name body:(NSString *) body
53
- {
54
- if (hasListeners) {// Only send events if anyone is listening
55
- [self sendEventWithName:name body:body];
56
- }
57
- }
58
- - (void)emitEventDict:(NSString *)name body:(NSDictionary *) body
59
- {
60
- NSError *error;
61
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:body
62
- options:NSJSONWritingPrettyPrinted
63
- error:&error];
64
-
65
- if (error) {
66
- NSLog(@"Got an error: %@", error);
67
- } else {
68
- NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
69
- [self emitEvent:name body:jsonString];
70
- }
71
- }
72
-
73
- - (dispatch_queue_t) methodQueue {
74
- if(commonTaskQueue == nil)
75
- commonTaskQueue = dispatch_queue_create("ReactNativeBlobUtil.queue", DISPATCH_QUEUE_SERIAL);
76
- return commonTaskQueue;
77
- }
78
-
79
-
80
- + (BOOL)requiresMainQueueSetup {
81
- return NO;
82
- }
83
-
84
- RCT_EXPORT_MODULE();
85
-
86
- - (id) init {
87
- self = [super init];
88
- self.filePathPrefix = FILE_PREFIX;
89
- if(commonTaskQueue == nil)
90
- commonTaskQueue = dispatch_queue_create("ReactNativeBlobUtil.queue", DISPATCH_QUEUE_SERIAL);
91
- if(fsQueue == nil)
92
- fsQueue = dispatch_queue_create("ReactNativeBlobUtil.fs.queue", DISPATCH_QUEUE_SERIAL);
93
- BOOL isDir;
94
- // if temp folder not exists, create one
95
- if(![[NSFileManager defaultManager] fileExistsAtPath: [ReactNativeBlobUtilFS getTempPath] isDirectory:&isDir]) {
96
- [[NSFileManager defaultManager] createDirectoryAtPath:[ReactNativeBlobUtilFS getTempPath] withIntermediateDirectories:YES attributes:nil error:NULL];
97
- }
98
-
99
- return self;
100
- }
101
-
102
- - (NSDictionary *)getConstants {
103
- return self.constantsToExport;
104
- }
105
-
106
- - (NSDictionary *)constantsToExport
107
- {
108
- return @{
109
- @"CacheDir" : [ReactNativeBlobUtilFS getCacheDir],
110
- @"DocumentDir": [ReactNativeBlobUtilFS getDocumentDir],
111
- @"DownloadDir" : [ReactNativeBlobUtilFS getDownloadDir],
112
- @"LibraryDir" : [ReactNativeBlobUtilFS getLibraryDir],
113
- @"MainBundleDir" : [ReactNativeBlobUtilFS getMainBundleDir],
114
- @"MovieDir" : [ReactNativeBlobUtilFS getMovieDir],
115
- @"MusicDir" : [ReactNativeBlobUtilFS getMusicDir],
116
- @"PictureDir" : [ReactNativeBlobUtilFS getPictureDir],
117
- @"ApplicationSupportDir" : [ReactNativeBlobUtilFS getApplicationSupportDir],
118
- // Android only. For the new architecture, we have a single spec for both platforms.
119
- @"RingtoneDir": @"",
120
- @"SDCardDir": @"",
121
- @"SDCardApplicationDir": @"",
122
- @"DCIMDir": @"",
123
- // Android only legacy constants
124
- @"LegacyDCIMDir": @"",
125
- @"LegacyPictureDir": @"",
126
- @"LegacyMusicDir": @"",
127
- @"LegacyDownloadDir": @"",
128
- @"LegacyMovieDir": @"",
129
- @"LegacyRingtoneDir": @"",
130
- @"LegacySDCardDir": @"",
131
- };
132
- }
133
-
134
- // Fetch blob data request
135
- RCT_EXPORT_METHOD(fetchBlobForm:(NSDictionary *)options
136
- taskId:(NSString *)taskId
137
- method:(NSString *)method
138
- url:(NSString *)url
139
- headers:(NSDictionary *)headers
140
- form:(NSArray *)form
141
- callback:(RCTResponseSenderBlock)callback)
142
- {
143
-
144
- [ReactNativeBlobUtilReqBuilder buildMultipartRequest:options
145
- taskId:taskId
146
- method:method
147
- url:url
148
- headers:headers
149
- form:form
150
- onComplete:^(__weak NSURLRequest *req, long bodyLength)
151
- {
152
- // something went wrong when building the request body
153
- if(req == nil)
154
- {
155
- callback(@[@"ReactNativeBlobUtil.fetchBlobForm failed to create request body"]);
156
- }
157
- // send HTTP request
158
- else
159
- {
160
- [[ReactNativeBlobUtilNetwork sharedInstance] sendRequest:options
161
- contentLength:bodyLength
162
- baseModule:self
163
- taskId:taskId
164
- withRequest:req
165
- callback:callback];
166
- }
167
- }];
168
-
169
- }
170
-
171
-
172
- // Fetch blob data request
173
- RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
174
- taskId:(NSString *)taskId
175
- method:(NSString *)method
176
- url:(NSString *)url
177
- headers:(NSDictionary *)headers
178
- body:(NSString *)body
179
- callback:(RCTResponseSenderBlock)callback)
180
- {
181
- [ReactNativeBlobUtilReqBuilder buildOctetRequest:options
182
- taskId:taskId
183
- method:method
184
- url:url
185
- headers:headers
186
- body:body
187
- onComplete:^(NSURLRequest *req, long bodyLength)
188
- {
189
- // something went wrong when building the request body
190
- if(req == nil)
191
- {
192
- callback(@[@"ReactNativeBlobUtil.fetchBlob failed to create request body"]);
193
- }
194
- // send HTTP request
195
- else
196
- {
197
- [[ReactNativeBlobUtilNetwork sharedInstance] sendRequest:options
198
- contentLength:bodyLength
199
- baseModule:self
200
- taskId:taskId
201
- withRequest:req
202
- callback:callback];
203
- }
204
- }];
205
- }
206
-
207
- #pragma mark - fs.createFile
208
- // Signature for the Old Architecture
209
- RCT_EXPORT_METHOD(createFile:(NSString *)path
210
- data:(NSString *)data
211
- encoding:(NSString *)encoding
212
- resolver:(RCTPromiseResolveBlock)resolve
213
- rejecter:(RCTPromiseRejectBlock)reject)
214
- {
215
- [self createFile:path data:data encoding:encoding resolve:resolve reject:reject];
216
- }
217
-
218
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
219
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
220
- - (void)createFile:(NSString *)path
221
- data:(NSString *)data
222
- encoding:(NSString *)encoding
223
- resolve:(RCTPromiseResolveBlock)resolve
224
- reject:(RCTPromiseRejectBlock)reject
225
- {
226
- NSFileManager * fm = [NSFileManager defaultManager];
227
- NSData * fileContent = nil;
228
-
229
- if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
230
- fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]];
231
- }
232
- else if([[encoding lowercaseString] isEqualToString:@"base64"]) {
233
- fileContent = [[NSData alloc] initWithBase64EncodedString:data options:0];
234
- }
235
- else if([[encoding lowercaseString] isEqualToString:@"uri"]) {
236
- NSString * orgPath = [data stringByReplacingOccurrencesOfString:FILE_PREFIX withString:@""];
237
- fileContent = [[NSData alloc] initWithContentsOfFile:orgPath];
238
- }
239
- else {
240
- fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
241
- }
242
-
243
- if ([fm fileExistsAtPath:path]) {
244
- reject(@"EEXIST", [NSString stringWithFormat:@"File '%@' already exists", path], nil);
245
- }
246
- else {
247
- BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
248
- if(success == YES)
249
- resolve(@[[NSNull null]]);
250
- else
251
- reject(@"EUNSPECIFIED", [NSString stringWithFormat:@"Failed to create new file at path '%@', please ensure the folder exists", path], nil);
252
- }
253
- }
254
-
255
- #pragma mark - fs.createFileASCII
256
- // method for create file with ASCII content
257
- // Signature for the Old Architecture
258
- RCT_EXPORT_METHOD(createFileASCII:(NSString *)path
259
- data:(NSArray *)dataArray
260
- resolver:(RCTPromiseResolveBlock)resolve
261
- rejecter:(RCTPromiseRejectBlock)reject)
262
- {
263
- [self createFileASCII:path data:dataArray resolve:resolve reject:reject];
264
- }
265
-
266
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
267
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
268
- - (void)createFileASCII:(NSString *)path
269
- data:(NSArray *)data
270
- resolve:(RCTPromiseResolveBlock)resolve
271
- reject:(RCTPromiseRejectBlock)reject
272
- {
273
- NSFileManager * fm = [NSFileManager defaultManager];
274
- NSMutableData * fileContent = [NSMutableData alloc];
275
- // prevent stack overflow, alloc on heap
276
- char * bytes = (char*) malloc([data count]);
277
-
278
- for(int i = 0; i < data.count; i++) {
279
- bytes[i] = [[data objectAtIndex:i] charValue];
280
- }
281
-
282
- [fileContent appendBytes:bytes length:data.count];
283
-
284
- if ([fm fileExistsAtPath:path]) {
285
- reject(@"EEXIST", [NSString stringWithFormat:@"File '%@' already exists", path], nil);
286
- }
287
- else {
288
- BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
289
- if(success == YES)
290
- resolve(@[[NSNull null]]);
291
- else
292
- reject(@"EUNSPECIFIED", [NSString stringWithFormat:@"failed to create new file at path '%@', please ensure the folder exists", path], nil);
293
- }
294
-
295
- free(bytes);
296
- }
297
-
298
- #pragma mark - fs.pathForAppGroup
299
- // Signature for the Old Architecture
300
- RCT_EXPORT_METHOD(pathForAppGroup:(NSString *)groupName
301
- resolver:(RCTPromiseResolveBlock)resolve
302
- rejecter:(RCTPromiseRejectBlock)reject)
303
- {
304
- [self pathForAppGroup:groupName resolve:resolve reject:reject];
305
- }
306
-
307
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
308
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
309
- - (void)pathForAppGroup:(NSString *)groupName
310
- resolve:(RCTPromiseResolveBlock)resolve
311
- reject:(RCTPromiseRejectBlock)reject
312
- {
313
- NSString * path = [ReactNativeBlobUtilFS getPathForAppGroup:groupName];
314
-
315
- if(path) {
316
- resolve(path);
317
- } else {
318
- reject(@"EUNSPECIFIED", @"could not find path for app group", nil);
319
- }
320
- }
321
-
322
- #pragma mark - fs.syncPathAppGroup
323
- RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(syncPathAppGroup:(NSString *)groupName) {
324
- NSURL *pathUrl = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupName];
325
- NSString *path = [pathUrl path];
326
-
327
- if(path) {
328
- return path;
329
- } else {
330
- return @"";
331
- }
332
- }
333
-
334
- #pragma mark - fs.exists
335
- RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callback) {
336
- [ReactNativeBlobUtilFS exists:path callback:callback];
337
- }
338
-
339
- #pragma mark - fs.writeFile
340
- // Signature for the Old Architecture
341
- RCT_EXPORT_METHOD(writeFile:(NSString *)path
342
- encoding:(NSString *)encoding
343
- data:(NSString *)data
344
- transformFile:(BOOL)transformFile
345
- append:(BOOL)append
346
- resolver:(RCTPromiseResolveBlock)resolve
347
- rejecter:(RCTPromiseRejectBlock)reject)
348
- {
349
- [self writeFile:path encoding:encoding data:data transformFile:transformFile append:append resolve:resolve reject:reject];
350
- }
351
-
352
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
353
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
354
- - (void)writeFile:(NSString *)path
355
- encoding:(NSString *)encoding
356
- data:(NSString *)data
357
- transformFile:(BOOL)transformFile
358
- append:(BOOL)append
359
- resolve:(RCTPromiseResolveBlock)resolve
360
- reject:(RCTPromiseRejectBlock)reject;
361
- {
362
- [ReactNativeBlobUtilFS writeFile:path encoding:[NSString stringWithString:encoding] data:data transformFile:transformFile append:append resolver:resolve rejecter:reject];
363
- }
364
-
365
- #pragma mark - fs.writeArray
366
- // Signature for the Old Architecture
367
- RCT_EXPORT_METHOD(writeFileArray:(NSString *)path
368
- data:(NSArray *)data
369
- append:(BOOL)append
370
- resolver:(RCTPromiseResolveBlock)resolve
371
- rejecter:(RCTPromiseRejectBlock)reject)
372
- {
373
- [self writeFileArray:path data:data append:append resolve:resolve reject:reject];
374
- }
375
-
376
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
377
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
378
- - (void)writeFileArray:(NSString *)path
379
- data:(NSArray *)data
380
- append:(BOOL)append
381
- resolve:(RCTPromiseResolveBlock)resolve
382
- reject:(RCTPromiseRejectBlock)reject
383
- {
384
- [ReactNativeBlobUtilFS writeFileArray:path data:data append:append resolver:resolve rejecter:reject];
385
- }
386
-
387
- #pragma mark - fs.writeStream
388
- RCT_EXPORT_METHOD(writeStream:(NSString *)path
389
- withEncoding:(NSString *)encoding
390
- appendData:(BOOL)append
391
- callback:(RCTResponseSenderBlock)callback)
392
- {
393
- ReactNativeBlobUtilFS * fileStream = [[ReactNativeBlobUtilFS alloc] init];
394
- NSFileManager * fm = [NSFileManager defaultManager];
395
- NSString * folder = [path stringByDeletingLastPathComponent];
396
- NSError* err = nil;
397
- BOOL isDir = NO;
398
- BOOL exists = [fm fileExistsAtPath:path isDirectory: &isDir];
399
-
400
- if(!exists) {
401
- [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
402
- if(err != nil) {
403
- callback(@[@"ENOTDIR", [NSString stringWithFormat:@"Failed to create parent directory of '%@'; error: %@", path, [err description]]]);
404
- }
405
- if(![fm createFileAtPath:path contents:nil attributes:nil]) {
406
- callback(@[@"ENOENT", [NSString stringWithFormat:@"File '%@' does not exist and could not be created", path]]);
407
- }
408
- }
409
- else if(isDir) {
410
- callback(@[@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", path]]);
411
- }
412
-
413
- NSString * streamId = [fileStream openWithPath:path encode:encoding appendData:append];
414
- callback(@[[NSNull null], [NSNull null], streamId]);
415
- }
416
-
417
- #pragma mark - fs.writeArrayChunk
418
- RCT_EXPORT_METHOD(writeArrayChunk:(NSString *)streamId
419
- withArray:(NSArray *)dataArray
420
- callback:(RCTResponseSenderBlock) callback)
421
- {
422
- ReactNativeBlobUtilFS *fs = [[ReactNativeBlobUtilFS getFileStreams] valueForKey:streamId];
423
- char * bytes = (char *) malloc([dataArray count]);
424
- for(int i = 0; i < dataArray.count; i++) {
425
- bytes[i] = [[dataArray objectAtIndex:i] charValue];
426
- }
427
- NSMutableData * data = [NSMutableData alloc];
428
- [data appendBytes:bytes length:dataArray.count];
429
- [fs write:data];
430
- free(bytes);
431
- callback(@[[NSNull null]]);
432
- }
433
-
434
- #pragma mark - fs.writeChunk
435
- RCT_EXPORT_METHOD(writeChunk:(NSString *)streamId
436
- withData:(NSString *)data
437
- callback:(RCTResponseSenderBlock) callback)
438
- {
439
- ReactNativeBlobUtilFS *fs = [[ReactNativeBlobUtilFS getFileStreams] valueForKey:streamId];
440
- [fs writeEncodeChunk:data];
441
- callback(@[[NSNull null]]);
442
- }
443
-
444
- #pragma mark - fs.closeStream
445
- RCT_EXPORT_METHOD(closeStream:(NSString *)streamId callback:(RCTResponseSenderBlock) callback)
446
- {
447
- ReactNativeBlobUtilFS *fs = [[ReactNativeBlobUtilFS getFileStreams] valueForKey:streamId];
448
- [fs closeOutStream];
449
- callback(@[[NSNull null], @YES]);
450
- }
451
-
452
- #pragma mark - unlink
453
- RCT_EXPORT_METHOD(unlink:(NSString *)path callback:(RCTResponseSenderBlock) callback)
454
- {
455
- NSError * error = nil;
456
- [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
457
- if(error == nil || [[NSFileManager defaultManager] fileExistsAtPath:path] == NO)
458
- callback(@[[NSNull null]]);
459
- else
460
- callback(@[[NSString stringWithFormat:@"failed to unlink file or path at %@", path]]);
461
- }
462
-
463
- #pragma mark - fs.removeSession
464
- RCT_EXPORT_METHOD(removeSession:(NSArray *)paths callback:(RCTResponseSenderBlock) callback)
465
- {
466
- NSError * error = nil;
467
-
468
- for(NSString * path in paths) {
469
- [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
470
- if(error != nil) {
471
- callback(@[[NSString stringWithFormat:@"failed to remove session path at %@", path]]);
472
- return;
473
- }
474
- }
475
- callback(@[[NSNull null]]);
476
-
477
- }
478
-
479
- #pragma mark - fs.ls
480
- // Signature for the Old Architecture
481
- RCT_EXPORT_METHOD(ls:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
482
- {
483
- [self ls:path resolve:resolve reject:reject];
484
- }
485
-
486
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
487
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
488
- - (void)ls:(NSString *)path
489
- resolve:(RCTPromiseResolveBlock)resolve
490
- reject:(RCTPromiseRejectBlock)reject
491
- {
492
- NSFileManager* fm = [NSFileManager defaultManager];
493
- BOOL exist = NO;
494
- BOOL isDir = NO;
495
- exist = [fm fileExistsAtPath:path isDirectory:&isDir];
496
- if(exist == NO) {
497
- return reject(@"ENOENT", [NSString stringWithFormat:@"No such file '%@'", path], nil);
498
- }
499
- if(isDir == NO) {
500
- return reject(@"ENOTDIR", [NSString stringWithFormat:@"Not a directory '%@'", path], nil);
501
- }
502
- NSError * error = nil;
503
- NSArray * result = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
504
-
505
- if(error == nil)
506
- resolve(result);
507
- else
508
- reject(@"EUNSPECIFIED", [error description], nil);
509
- }
510
-
511
- #pragma mark - fs.stat
512
- RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) callback)
513
- {
514
-
515
- [ReactNativeBlobUtilFS getPathFromUri:target completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
516
- __block NSMutableDictionary * result;
517
- if(path != nil)
518
- {
519
- NSFileManager* fm = [NSFileManager defaultManager];
520
- BOOL exist = NO;
521
- BOOL isDir = NO;
522
- NSError * error = nil;
523
-
524
- exist = [fm fileExistsAtPath:path isDirectory:&isDir];
525
- if(exist == NO) {
526
- callback(@[[NSString stringWithFormat:@"failed to stat path `%@` because it does not exist or it is not a folder", path]]);
527
- return ;
528
- }
529
- result = [ReactNativeBlobUtilFS stat:path error:&error].mutableCopy;
530
-
531
- if(error == nil)
532
- callback(@[[NSNull null], result]);
533
- else
534
- callback(@[[error localizedDescription], [NSNull null]]);
535
-
536
- }
537
- else if(asset != nil)
538
- {
539
- __block NSNumber * size = [NSNumber numberWithLong:[asset size]];
540
- result = [asset metadata];
541
- [result setValue:size forKey:@"size"];
542
- callback(@[[NSNull null], result]);
543
- }
544
- else
545
- {
546
- callback(@[@"failed to stat path, could not resolve URI", [NSNull null]]);
547
- }
548
- }];
549
- }
550
-
551
- #pragma mark - fs.lstat
552
- RCT_EXPORT_METHOD(lstat:(NSString *)path callback:(RCTResponseSenderBlock) callback)
553
- {
554
- NSFileManager* fm = [NSFileManager defaultManager];
555
- BOOL exist = NO;
556
- BOOL isDir = NO;
557
-
558
- path = [ReactNativeBlobUtilFS getPathOfAsset:path];
559
-
560
- exist = [fm fileExistsAtPath:path isDirectory:&isDir];
561
- if(exist == NO) {
562
- callback(@[[NSString stringWithFormat:@"failed to lstat path `%@` because it does not exist or it is not a folder", path]]);
563
- return ;
564
- }
565
- NSError * error = nil;
566
- NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
567
-
568
- NSMutableArray * res = [[NSMutableArray alloc] init];
569
- if(isDir == YES) {
570
- for(NSString * p in files) {
571
- NSString * filePath = [NSString stringWithFormat:@"%@/%@", path, p];
572
- [res addObject:[ReactNativeBlobUtilFS stat:filePath error:&error]];
573
- }
574
- }
575
- else {
576
- [res addObject:[ReactNativeBlobUtilFS stat:path error:&error]];
577
- }
578
-
579
- if(error == nil)
580
- callback(@[[NSNull null], res == nil ? [NSNull null] :res ]);
581
- else
582
- callback(@[[error localizedDescription], [NSNull null]]);
583
-
584
- }
585
-
586
- #pragma mark - fs.cp
587
- // Signature for the Old Architecture
588
- RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
589
- {
590
- [self cp:src dest:dest callback:callback];
591
- }
592
-
593
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
594
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
595
- - (void)cp:(NSString *)src
596
- dest:(NSString *)dest
597
- callback:(RCTResponseSenderBlock)callback
598
- {
599
- // path = [ReactNativeBlobUtilFS getPathOfAsset:path];
600
- [ReactNativeBlobUtilFS getPathFromUri:src completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
601
- NSError * error = nil;
602
- if(path == nil)
603
- {
604
- [ReactNativeBlobUtilFS writeAssetToPath:asset dest:dest];
605
- callback(@[[NSNull null], @YES]);
606
- }
607
- else
608
- {
609
- // If the destination exists there will be an error
610
- BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
611
-
612
- if(error == nil)
613
- callback(@[[NSNull null], @YES]);
614
- else
615
- callback(@[[error localizedDescription], @NO]);
616
- }
617
- }];
618
- }
619
-
620
- #pragma mark - fs.mv
621
- // Signature for the Old Architecture
622
- RCT_EXPORT_METHOD(mv:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
623
- {
624
- [self mv:path dest:dest callback:callback];
625
- }
626
-
627
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
628
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
629
- - (void)mv:(NSString *)path
630
- dest:(NSString *)dest
631
- callback:(RCTResponseSenderBlock)callback
632
- {
633
- NSError * error = nil;
634
- BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
635
-
636
- if(error == nil)
637
- callback(@[[NSNull null], @YES]);
638
- else
639
- callback(@[[error localizedDescription], @NO]);
640
-
641
- }
642
-
643
- #pragma mark - fs.mkdir
644
- RCT_EXPORT_METHOD(mkdir:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
645
- {
646
- [self mkdir:path resolve:resolve reject:reject];
647
- }
648
-
649
- - (void)mkdir:(NSString *)path
650
- resolve:(RCTPromiseResolveBlock)resolve
651
- reject:(RCTPromiseRejectBlock)reject
652
- {
653
- [ReactNativeBlobUtilFS mkdir:path resolver:resolve rejecter:reject];
654
- }
655
-
656
- #pragma mark - fs.readFile
657
- // Signature for the Old Architecture
658
- RCT_EXPORT_METHOD(readFile:(NSString *)path
659
- encoding:(NSString *)encoding
660
- transformFile:(BOOL) transformFile
661
- resolver:(RCTPromiseResolveBlock)resolve
662
- rejecter:(RCTPromiseRejectBlock)reject)
663
- {
664
- [self readFile:path encoding:encoding transformFile:transformFile resolve:resolve reject:reject];
665
- }
666
-
667
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
668
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
669
- - (void)readFile:(NSString *)path
670
- encoding:(NSString *)encoding
671
- transformFile:(BOOL)transformFile
672
- resolve:(RCTPromiseResolveBlock)resolve
673
- reject:(RCTPromiseRejectBlock)reject
674
- {
675
-
676
- [ReactNativeBlobUtilFS readFile:path encoding:encoding transformFile:transformFile onComplete:^(NSData * content, NSString * code, NSString * err) {
677
- if(err != nil) {
678
- reject(code, err, nil);
679
- return;
680
- }
681
- if([encoding isEqualToString:@"ascii"]) {
682
- resolve((NSMutableArray *)content);
683
- }
684
- if([encoding isEqualToString:@"base64"]) {
685
- resolve([content base64EncodedStringWithOptions:0]);
686
- } else {
687
- resolve([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]);
688
- }
689
- }];
690
- }
691
-
692
- #pragma mark - fs.hash
693
- // Signature for the Old Architecture
694
- RCT_EXPORT_METHOD(hash:(NSString *)path
695
- algorithm:(NSString *)algorithm
696
- resolver:(RCTPromiseResolveBlock)resolve
697
- rejecter:(RCTPromiseRejectBlock)reject)
698
- {
699
- [self hash:path algorithm:algorithm resolve:resolve reject:reject];
700
- }
701
-
702
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
703
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
704
- - (void)hash:(NSString *)path
705
- algorithm:(NSString *)algorithm
706
- resolve:(RCTPromiseResolveBlock)resolve
707
- reject:(RCTPromiseRejectBlock)reject
708
- {
709
- [ReactNativeBlobUtilFS hash:path algorithm:[NSString stringWithString:algorithm] resolver:resolve rejecter:reject];
710
- }
711
-
712
- #pragma mark - fs.readStream
713
- RCT_EXPORT_METHOD(readStream:(NSString *)path encoding:(NSString *)encoding bufferSize:(int)bufferSize tick:(int)tick streamId:(NSString *)streamId)
714
- {
715
- if(bufferSize == 0) {
716
- if([[encoding lowercaseString] isEqualToString:@"base64"])
717
- bufferSize = 4095;
718
- else
719
- bufferSize = 4096;
720
- }
721
-
722
- dispatch_async(fsQueue, ^{
723
- [ReactNativeBlobUtilFS readStream:path encoding:encoding bufferSize:bufferSize tick:tick streamId:streamId baseModule:self];
724
- });
725
- }
726
-
727
- #pragma mark - fs.getEnvironmentDirs
728
- RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback)
729
- {
730
-
731
- callback(@[
732
- [ReactNativeBlobUtilFS getDocumentDir],
733
- [ReactNativeBlobUtilFS getCacheDir],
734
- ]);
735
- }
736
-
737
- #pragma mark - net.cancelRequest
738
- RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBlock)callback) {
739
- [[ReactNativeBlobUtilNetwork sharedInstance] cancelRequest:taskId];
740
- callback(@[[NSNull null], taskId]);
741
-
742
- }
743
-
744
- #pragma mark - net.enableProgressReport
745
- RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
746
- {
747
-
748
- ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Download interval:interval count:count];
749
- [[ReactNativeBlobUtilNetwork sharedInstance] enableProgressReport:taskId config:cfg];
750
- }
751
-
752
- #pragma mark - net.enableUploadProgressReport
753
- RCT_EXPORT_METHOD(enableUploadProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
754
- {
755
- ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Upload interval:interval count:count];
756
- [[ReactNativeBlobUtilNetwork sharedInstance] enableUploadProgress:taskId config:cfg];
757
- }
758
-
759
- #pragma mark - fs.slice
760
- // Signature for the Old Architecture
761
- RCT_EXPORT_METHOD(slice:(NSString *)src dest:(NSString *)dest start:(nonnull NSNumber *)start end:(nonnull NSNumber *)end resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
762
- {
763
- [self slice:src dest:dest start:start.doubleValue end:end.doubleValue resolve:resolve reject:reject];
764
- }
765
-
766
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
767
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
768
- - (void)slice:(NSString *)src
769
- dest:(NSString *)dest
770
- start:(double)start
771
- end:(double)end
772
- resolve:(RCTPromiseResolveBlock)resolve
773
- reject:(RCTPromiseRejectBlock)reject
774
- {
775
- [ReactNativeBlobUtilFS slice:src dest:dest start:@(start) end:@(end) encode:@"" resolver:resolve rejecter:reject];
776
- }
777
-
778
- // Signature for the Old Architecture
779
- RCT_EXPORT_METHOD(presentOptionsMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
780
- {
781
- [self presentOptionsMenu:uri scheme:scheme resolve:resolve reject:reject];
782
- }
783
-
784
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
785
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
786
- - (void)presentOptionsMenu:(NSString *)uri
787
- scheme:(NSString *)scheme
788
- resolve:(RCTPromiseResolveBlock)resolve
789
- reject:(RCTPromiseRejectBlock)reject
790
- {
791
- NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
792
- NSURL * url = [[NSURL alloc] initWithString:utf8uri];
793
- // NSURL * url = [[NSURL alloc] initWithString:uri];
794
- documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
795
- UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
796
- documentController.delegate = self;
797
- if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
798
- CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
799
- dispatch_sync(dispatch_get_main_queue(), ^{
800
- [documentController presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES];
801
- });
802
- resolve(@[[NSNull null]]);
803
- } else {
804
- reject(@"EINVAL", @"scheme is not supported", nil);
805
- }
806
- }
807
-
808
- // Signature for the Old Architecture
809
- RCT_EXPORT_METHOD(presentOpenInMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
810
- {
811
- [self presentOpenInMenu:uri scheme:scheme resolve:resolve reject:reject];
812
- }
813
-
814
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
815
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
816
- - (void)presentOpenInMenu:(NSString *)uri
817
- scheme:(NSString *)scheme
818
- resolve:(RCTPromiseResolveBlock)resolve
819
- reject:(RCTPromiseRejectBlock)reject
820
- {
821
- NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
822
- NSURL * url = [[NSURL alloc] initWithString:utf8uri];
823
- documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
824
- UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
825
- documentController.delegate = self;
826
- if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
827
- CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
828
- dispatch_sync(dispatch_get_main_queue(), ^{
829
- [documentController presentOpenInMenuFromRect:rect inView:rootCtrl.view animated:YES];
830
- });
831
- resolve(@[[NSNull null]]);
832
- } else {
833
- reject(@"EINVAL", @"scheme is not supported", nil);
834
- }
835
- }
836
-
837
- # pragma mark - open file with UIDocumentInteractionController and delegate
838
- // Signature for the Old Architecture
839
- RCT_EXPORT_METHOD(presentPreview:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
840
- {
841
- [self presentPreview:uri scheme:scheme resolve:resolve reject:reject];
842
- }
843
-
844
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
845
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
846
- - (void)presentPreview:(NSString *)uri
847
- scheme:(NSString *)scheme
848
- resolve:(RCTPromiseResolveBlock)resolve
849
- reject:(RCTPromiseRejectBlock)reject
850
- {
851
- NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
852
- NSURL * url = [[NSURL alloc] initWithString:utf8uri];
853
- // NSURL * url = [[NSURL alloc] initWithString:uri];
854
- documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
855
- documentController.delegate = self;
856
-
857
- if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
858
- dispatch_sync(dispatch_get_main_queue(), ^{
859
- if([documentController presentPreviewAnimated:YES]) {
860
- resolve(@[[NSNull null]]);
861
- } else {
862
- reject(@"EINVAL", @"document is not supported", nil);
863
- }
864
- });
865
- } else {
866
- reject(@"EINVAL", @"scheme is not supported", nil);
867
- }
868
- }
869
-
870
- # pragma mark - exclude from backup key
871
-
872
- RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
873
- {
874
- [self excludeFromBackupKey:url resolve:resolve reject:reject];
875
- }
876
-
877
- - (void)excludeFromBackupKey:(NSString *)url
878
- resolve:(RCTPromiseResolveBlock)resolve
879
- reject:(RCTPromiseRejectBlock)reject
880
- {
881
- NSError *error = nil;
882
- [ [NSURL URLWithString:url] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
883
- if(!error)
884
- {
885
- resolve(@[[NSNull null]]);
886
- } else {
887
- reject(@"EUNSPECIFIED", [error description], nil);
888
- }
889
-
890
- }
891
-
892
-
893
- RCT_EXPORT_METHOD(df:(RCTResponseSenderBlock)callback)
894
- {
895
- [ReactNativeBlobUtilFS df:callback];
896
- }
897
-
898
- - (UIViewController *)documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
899
- {
900
- UIWindow *window = [UIApplication sharedApplication].keyWindow;
901
- return window.rootViewController;
902
- }
903
-
904
- # pragma mark - Android Only methods
905
- // These methods are required because in the New Arch we have a single spec for both platforms
906
- - (void)actionViewIntent:(NSString *) path
907
- mime:(NSString *) mime
908
- chooserTitle:(NSString *) chooserTitle
909
- resolve:(RCTPromiseResolveBlock)resolve
910
- reject:(RCTPromiseRejectBlock)reject
911
- {
912
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
913
- }
914
-
915
- - (void)addCompleteDownload:(NSDictionary *)config
916
- resolve:(RCTPromiseResolveBlock)resolve
917
- reject:(RCTPromiseRejectBlock)reject
918
- {
919
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
920
- }
921
-
922
- - (void)copyToInternal:(NSString *)contentUri
923
- destpath:(NSString *) destpath
924
- resolve:(RCTPromiseResolveBlock)resolve
925
- reject:(RCTPromiseRejectBlock)reject
926
- {
927
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
928
- }
929
- - (void)copyToMediaStore:(NSDictionary *)filedata
930
- mt:(NSString *) mt
931
- path:(NSString *) path
932
- resolve:(RCTPromiseResolveBlock)resolve
933
- reject:(RCTPromiseRejectBlock)reject
934
- {
935
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
936
- }
937
-
938
- - (void)createMediaFile:(NSDictionary *)filedata
939
- mt:(NSString *) mt
940
- resolve:(RCTPromiseResolveBlock)resolve
941
- reject:(RCTPromiseRejectBlock)reject
942
- {
943
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
944
- }
945
-
946
- - (void)getBlob:(NSString *)contentUri
947
- encoding:(NSString *)encoding
948
- resolve:(RCTPromiseResolveBlock)resolve
949
- reject:(RCTPromiseRejectBlock)reject
950
- {
951
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
952
- }
953
-
954
- - (void)getContentIntent:(NSString *)mime
955
- resolve:(RCTPromiseResolveBlock)resolve
956
- reject:(RCTPromiseRejectBlock)reject
957
- {
958
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
959
- }
960
- - (void)getSDCardDir:(RCTPromiseResolveBlock)resolve
961
- reject:(RCTPromiseRejectBlock)reject
962
- {
963
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
964
- }
965
- - (void)getSDCardApplicationDir:(RCTPromiseResolveBlock)resolve
966
- reject:(RCTPromiseRejectBlock)reject
967
- {
968
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
969
- }
970
- - (void)scanFile:(NSArray *)pairs
971
- callback:(RCTResponseSenderBlock)callback
972
- {
973
- callback(@[@"Scan file method not supported in iOS"]);
974
- }
975
- - (void)writeToMediaFile:(NSString *)fileUri
976
- path:(NSString *)path
977
- transformFile:(BOOL)transformFile
978
- resolve:(RCTPromiseResolveBlock)resolve
979
- reject:(RCTPromiseRejectBlock)reject
980
- {
981
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
982
- }
983
-
984
- # pragma mark - New Architecture
985
- #if RCT_NEW_ARCH_ENABLED
986
- - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
987
- (const facebook::react::ObjCTurboModule::InitParams &)params
988
- {
989
- return std::make_shared<facebook::react::NativeBlobUtilsSpecJSI>(params);
990
- }
991
- #endif
992
-
993
- @end
1
+ //
2
+ // ReactNativeBlobUtil.m
3
+ //
4
+ // Created by wkh237 on 2016/4/28.
5
+ //
6
+
7
+ #import "ReactNativeBlobUtil.h"
8
+ #import "ReactNativeBlobUtilFS.h"
9
+ #import "ReactNativeBlobUtilNetwork.h"
10
+ #import "ReactNativeBlobUtilConst.h"
11
+ #import "ReactNativeBlobUtilReqBuilder.h"
12
+ #import "ReactNativeBlobUtilProgress.h"
13
+
14
+ #if RCT_NEW_ARCH_ENABLED
15
+ #import <ReactNativeBlobUtilSpec/ReactNativeBlobUtilSpec.h>
16
+ #endif
17
+
18
+ dispatch_queue_t commonTaskQueue;
19
+ dispatch_queue_t fsQueue;
20
+
21
+ ////////////////////////////////////////
22
+ //
23
+ // Exported native methods
24
+ //
25
+ ////////////////////////////////////////
26
+
27
+ #pragma mark ReactNativeBlobUtil exported methods
28
+
29
+ @implementation ReactNativeBlobUtil
30
+
31
+ @synthesize filePathPrefix;
32
+ @synthesize documentController;
33
+ @synthesize bridge;
34
+ static bool hasListeners = NO;
35
+
36
+ - (NSArray<NSString*> *)supportedEvents {
37
+ return @[@"ReactNativeBlobUtilState", @"ReactNativeBlobUtilServerPush", @"ReactNativeBlobUtilProgress", @"ReactNativeBlobUtilProgress-upload", @"ReactNativeBlobUtilExpire", @"ReactNativeBlobUtilMessage", @"ReactNativeBlobUtilFilesystem", @"log", @"warn", @"error", @"data", @"end", @"reportProgress", @"reportUploadProgress"];
38
+ }
39
+
40
+ // Will be called when this module's first listener is added.
41
+ -(void)startObserving {
42
+ hasListeners = YES;
43
+ // Set up any upstream listeners or background tasks as necessary
44
+ }
45
+
46
+ // Will be called when this module's last listener is removed, or on dealloc.
47
+ -(void)stopObserving {
48
+ hasListeners = NO;
49
+ // Remove upstream listeners, stop unnecessary background tasks
50
+ }
51
+
52
+ - (void)emitEvent:(NSString *)name body:(NSString *) body
53
+ {
54
+ if (hasListeners) {// Only send events if anyone is listening
55
+ [self sendEventWithName:name body:body];
56
+ }
57
+ }
58
+ - (void)emitEventDict:(NSString *)name body:(NSDictionary *) body
59
+ {
60
+ NSError *error;
61
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:body
62
+ options:NSJSONWritingPrettyPrinted
63
+ error:&error];
64
+
65
+ if (error) {
66
+ NSLog(@"Got an error: %@", error);
67
+ } else {
68
+ NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
69
+ [self emitEvent:name body:jsonString];
70
+ }
71
+ }
72
+
73
+ - (dispatch_queue_t) methodQueue {
74
+ if(commonTaskQueue == nil)
75
+ commonTaskQueue = dispatch_queue_create("ReactNativeBlobUtil.queue", DISPATCH_QUEUE_SERIAL);
76
+ return commonTaskQueue;
77
+ }
78
+
79
+
80
+ + (BOOL)requiresMainQueueSetup {
81
+ return NO;
82
+ }
83
+
84
+ RCT_EXPORT_MODULE();
85
+
86
+ - (id) init {
87
+ self = [super init];
88
+ self.filePathPrefix = FILE_PREFIX;
89
+ if(commonTaskQueue == nil)
90
+ commonTaskQueue = dispatch_queue_create("ReactNativeBlobUtil.queue", DISPATCH_QUEUE_SERIAL);
91
+ if(fsQueue == nil)
92
+ fsQueue = dispatch_queue_create("ReactNativeBlobUtil.fs.queue", DISPATCH_QUEUE_SERIAL);
93
+ BOOL isDir;
94
+ // if temp folder not exists, create one
95
+ if(![[NSFileManager defaultManager] fileExistsAtPath: [ReactNativeBlobUtilFS getTempPath] isDirectory:&isDir]) {
96
+ [[NSFileManager defaultManager] createDirectoryAtPath:[ReactNativeBlobUtilFS getTempPath] withIntermediateDirectories:YES attributes:nil error:NULL];
97
+ }
98
+
99
+ return self;
100
+ }
101
+
102
+ - (NSDictionary *)getConstants {
103
+ return self.constantsToExport;
104
+ }
105
+
106
+ - (NSDictionary *)constantsToExport
107
+ {
108
+ return @{
109
+ @"CacheDir" : [ReactNativeBlobUtilFS getCacheDir],
110
+ @"DocumentDir": [ReactNativeBlobUtilFS getDocumentDir],
111
+ @"DownloadDir" : [ReactNativeBlobUtilFS getDownloadDir],
112
+ @"LibraryDir" : [ReactNativeBlobUtilFS getLibraryDir],
113
+ @"MainBundleDir" : [ReactNativeBlobUtilFS getMainBundleDir],
114
+ @"MovieDir" : [ReactNativeBlobUtilFS getMovieDir],
115
+ @"MusicDir" : [ReactNativeBlobUtilFS getMusicDir],
116
+ @"PictureDir" : [ReactNativeBlobUtilFS getPictureDir],
117
+ @"ApplicationSupportDir" : [ReactNativeBlobUtilFS getApplicationSupportDir],
118
+ // Android only. For the new architecture, we have a single spec for both platforms.
119
+ @"RingtoneDir": @"",
120
+ @"SDCardDir": @"",
121
+ @"SDCardApplicationDir": @"",
122
+ @"DCIMDir": @"",
123
+ // Android only legacy constants
124
+ @"LegacyDCIMDir": @"",
125
+ @"LegacyPictureDir": @"",
126
+ @"LegacyMusicDir": @"",
127
+ @"LegacyDownloadDir": @"",
128
+ @"LegacyMovieDir": @"",
129
+ @"LegacyRingtoneDir": @"",
130
+ @"LegacySDCardDir": @"",
131
+ };
132
+ }
133
+
134
+ // Fetch blob data request
135
+ RCT_EXPORT_METHOD(fetchBlobForm:(NSDictionary *)options
136
+ taskId:(NSString *)taskId
137
+ method:(NSString *)method
138
+ url:(NSString *)url
139
+ headers:(NSDictionary *)headers
140
+ form:(NSArray *)form
141
+ callback:(RCTResponseSenderBlock)callback)
142
+ {
143
+
144
+ [ReactNativeBlobUtilReqBuilder buildMultipartRequest:options
145
+ taskId:taskId
146
+ method:method
147
+ url:url
148
+ headers:headers
149
+ form:form
150
+ onComplete:^(__weak NSURLRequest *req, long bodyLength)
151
+ {
152
+ // something went wrong when building the request body
153
+ if(req == nil)
154
+ {
155
+ callback(@[@"ReactNativeBlobUtil.fetchBlobForm failed to create request body"]);
156
+ }
157
+ // send HTTP request
158
+ else
159
+ {
160
+ [[ReactNativeBlobUtilNetwork sharedInstance] sendRequest:options
161
+ contentLength:bodyLength
162
+ baseModule:self
163
+ taskId:taskId
164
+ withRequest:req
165
+ callback:callback];
166
+ }
167
+ }];
168
+
169
+ }
170
+
171
+
172
+ // Fetch blob data request
173
+ RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
174
+ taskId:(NSString *)taskId
175
+ method:(NSString *)method
176
+ url:(NSString *)url
177
+ headers:(NSDictionary *)headers
178
+ body:(NSString *)body
179
+ callback:(RCTResponseSenderBlock)callback)
180
+ {
181
+ [ReactNativeBlobUtilReqBuilder buildOctetRequest:options
182
+ taskId:taskId
183
+ method:method
184
+ url:url
185
+ headers:headers
186
+ body:body
187
+ onComplete:^(NSURLRequest *req, long bodyLength)
188
+ {
189
+ // something went wrong when building the request body
190
+ if(req == nil)
191
+ {
192
+ callback(@[@"ReactNativeBlobUtil.fetchBlob failed to create request body"]);
193
+ }
194
+ // send HTTP request
195
+ else
196
+ {
197
+ [[ReactNativeBlobUtilNetwork sharedInstance] sendRequest:options
198
+ contentLength:bodyLength
199
+ baseModule:self
200
+ taskId:taskId
201
+ withRequest:req
202
+ callback:callback];
203
+ }
204
+ }];
205
+ }
206
+
207
+ #pragma mark - fs.createFile
208
+ // Signature for the Old Architecture
209
+ RCT_EXPORT_METHOD(createFile:(NSString *)path
210
+ data:(NSString *)data
211
+ encoding:(NSString *)encoding
212
+ resolver:(RCTPromiseResolveBlock)resolve
213
+ rejecter:(RCTPromiseRejectBlock)reject)
214
+ {
215
+ [self createFile:path data:data encoding:encoding resolve:resolve reject:reject];
216
+ }
217
+
218
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
219
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
220
+ - (void)createFile:(NSString *)path
221
+ data:(NSString *)data
222
+ encoding:(NSString *)encoding
223
+ resolve:(RCTPromiseResolveBlock)resolve
224
+ reject:(RCTPromiseRejectBlock)reject
225
+ {
226
+ NSFileManager * fm = [NSFileManager defaultManager];
227
+ NSData * fileContent = nil;
228
+
229
+ if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
230
+ fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]];
231
+ }
232
+ else if([[encoding lowercaseString] isEqualToString:@"base64"]) {
233
+ fileContent = [[NSData alloc] initWithBase64EncodedString:data options:0];
234
+ }
235
+ else if([[encoding lowercaseString] isEqualToString:@"uri"]) {
236
+ NSString * orgPath = [data stringByReplacingOccurrencesOfString:FILE_PREFIX withString:@""];
237
+ fileContent = [[NSData alloc] initWithContentsOfFile:orgPath];
238
+ }
239
+ else {
240
+ fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
241
+ }
242
+
243
+ if ([fm fileExistsAtPath:path]) {
244
+ reject(@"EEXIST", [NSString stringWithFormat:@"File '%@' already exists", path], nil);
245
+ }
246
+ else {
247
+ BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
248
+ if(success == YES)
249
+ resolve(@[[NSNull null]]);
250
+ else
251
+ reject(@"EUNSPECIFIED", [NSString stringWithFormat:@"Failed to create new file at path '%@', please ensure the folder exists", path], nil);
252
+ }
253
+ }
254
+
255
+ #pragma mark - fs.createFileASCII
256
+ // method for create file with ASCII content
257
+ // Signature for the Old Architecture
258
+ RCT_EXPORT_METHOD(createFileASCII:(NSString *)path
259
+ data:(NSArray *)dataArray
260
+ resolver:(RCTPromiseResolveBlock)resolve
261
+ rejecter:(RCTPromiseRejectBlock)reject)
262
+ {
263
+ [self createFileASCII:path data:dataArray resolve:resolve reject:reject];
264
+ }
265
+
266
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
267
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
268
+ - (void)createFileASCII:(NSString *)path
269
+ data:(NSArray *)data
270
+ resolve:(RCTPromiseResolveBlock)resolve
271
+ reject:(RCTPromiseRejectBlock)reject
272
+ {
273
+ NSFileManager * fm = [NSFileManager defaultManager];
274
+ NSMutableData * fileContent = [NSMutableData alloc];
275
+ // prevent stack overflow, alloc on heap
276
+ char * bytes = (char*) malloc([data count]);
277
+
278
+ for(int i = 0; i < data.count; i++) {
279
+ bytes[i] = [[data objectAtIndex:i] charValue];
280
+ }
281
+
282
+ [fileContent appendBytes:bytes length:data.count];
283
+
284
+ if ([fm fileExistsAtPath:path]) {
285
+ reject(@"EEXIST", [NSString stringWithFormat:@"File '%@' already exists", path], nil);
286
+ }
287
+ else {
288
+ BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
289
+ if(success == YES)
290
+ resolve(@[[NSNull null]]);
291
+ else
292
+ reject(@"EUNSPECIFIED", [NSString stringWithFormat:@"failed to create new file at path '%@', please ensure the folder exists", path], nil);
293
+ }
294
+
295
+ free(bytes);
296
+ }
297
+
298
+ #pragma mark - fs.pathForAppGroup
299
+ // Signature for the Old Architecture
300
+ RCT_EXPORT_METHOD(pathForAppGroup:(NSString *)groupName
301
+ resolver:(RCTPromiseResolveBlock)resolve
302
+ rejecter:(RCTPromiseRejectBlock)reject)
303
+ {
304
+ [self pathForAppGroup:groupName resolve:resolve reject:reject];
305
+ }
306
+
307
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
308
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
309
+ - (void)pathForAppGroup:(NSString *)groupName
310
+ resolve:(RCTPromiseResolveBlock)resolve
311
+ reject:(RCTPromiseRejectBlock)reject
312
+ {
313
+ NSString * path = [ReactNativeBlobUtilFS getPathForAppGroup:groupName];
314
+
315
+ if(path) {
316
+ resolve(path);
317
+ } else {
318
+ reject(@"EUNSPECIFIED", @"could not find path for app group", nil);
319
+ }
320
+ }
321
+
322
+ #pragma mark - fs.syncPathAppGroup
323
+ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(syncPathAppGroup:(NSString *)groupName) {
324
+ NSURL *pathUrl = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupName];
325
+ NSString *path = [pathUrl path];
326
+
327
+ if(path) {
328
+ return path;
329
+ } else {
330
+ return @"";
331
+ }
332
+ }
333
+
334
+ #pragma mark - fs.exists
335
+ RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callback) {
336
+ [ReactNativeBlobUtilFS exists:path callback:callback];
337
+ }
338
+
339
+ #pragma mark - fs.writeFile
340
+ // Signature for the Old Architecture
341
+ RCT_EXPORT_METHOD(writeFile:(NSString *)path
342
+ encoding:(NSString *)encoding
343
+ data:(NSString *)data
344
+ transformFile:(BOOL)transformFile
345
+ append:(BOOL)append
346
+ resolver:(RCTPromiseResolveBlock)resolve
347
+ rejecter:(RCTPromiseRejectBlock)reject)
348
+ {
349
+ [self writeFile:path encoding:encoding data:data transformFile:transformFile append:append resolve:resolve reject:reject];
350
+ }
351
+
352
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
353
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
354
+ - (void)writeFile:(NSString *)path
355
+ encoding:(NSString *)encoding
356
+ data:(NSString *)data
357
+ transformFile:(BOOL)transformFile
358
+ append:(BOOL)append
359
+ resolve:(RCTPromiseResolveBlock)resolve
360
+ reject:(RCTPromiseRejectBlock)reject;
361
+ {
362
+ [ReactNativeBlobUtilFS writeFile:path encoding:[NSString stringWithString:encoding] data:data transformFile:transformFile append:append resolver:resolve rejecter:reject];
363
+ }
364
+
365
+ #pragma mark - fs.writeArray
366
+ // Signature for the Old Architecture
367
+ RCT_EXPORT_METHOD(writeFileArray:(NSString *)path
368
+ data:(NSArray *)data
369
+ append:(BOOL)append
370
+ resolver:(RCTPromiseResolveBlock)resolve
371
+ rejecter:(RCTPromiseRejectBlock)reject)
372
+ {
373
+ [self writeFileArray:path data:data append:append resolve:resolve reject:reject];
374
+ }
375
+
376
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
377
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
378
+ - (void)writeFileArray:(NSString *)path
379
+ data:(NSArray *)data
380
+ append:(BOOL)append
381
+ resolve:(RCTPromiseResolveBlock)resolve
382
+ reject:(RCTPromiseRejectBlock)reject
383
+ {
384
+ [ReactNativeBlobUtilFS writeFileArray:path data:data append:append resolver:resolve rejecter:reject];
385
+ }
386
+
387
+ #pragma mark - fs.writeStream
388
+ RCT_EXPORT_METHOD(writeStream:(NSString *)path
389
+ withEncoding:(NSString *)encoding
390
+ appendData:(BOOL)append
391
+ callback:(RCTResponseSenderBlock)callback)
392
+ {
393
+ ReactNativeBlobUtilFS * fileStream = [[ReactNativeBlobUtilFS alloc] init];
394
+ NSFileManager * fm = [NSFileManager defaultManager];
395
+ NSString * folder = [path stringByDeletingLastPathComponent];
396
+ NSError* err = nil;
397
+ BOOL isDir = NO;
398
+ BOOL exists = [fm fileExistsAtPath:path isDirectory: &isDir];
399
+
400
+ if(!exists) {
401
+ [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
402
+ if(err != nil) {
403
+ callback(@[@"ENOTDIR", [NSString stringWithFormat:@"Failed to create parent directory of '%@'; error: %@", path, [err description]]]);
404
+ }
405
+ if(![fm createFileAtPath:path contents:nil attributes:nil]) {
406
+ callback(@[@"ENOENT", [NSString stringWithFormat:@"File '%@' does not exist and could not be created", path]]);
407
+ }
408
+ }
409
+ else if(isDir) {
410
+ callback(@[@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", path]]);
411
+ }
412
+
413
+ NSString * streamId = [fileStream openWithPath:path encode:encoding appendData:append];
414
+ callback(@[[NSNull null], [NSNull null], streamId]);
415
+ }
416
+
417
+ #pragma mark - fs.writeArrayChunk
418
+ RCT_EXPORT_METHOD(writeArrayChunk:(NSString *)streamId
419
+ withArray:(NSArray *)dataArray
420
+ callback:(RCTResponseSenderBlock) callback)
421
+ {
422
+ ReactNativeBlobUtilFS *fs = [[ReactNativeBlobUtilFS getFileStreams] valueForKey:streamId];
423
+ char * bytes = (char *) malloc([dataArray count]);
424
+ for(int i = 0; i < dataArray.count; i++) {
425
+ bytes[i] = [[dataArray objectAtIndex:i] charValue];
426
+ }
427
+ NSMutableData * data = [NSMutableData alloc];
428
+ [data appendBytes:bytes length:dataArray.count];
429
+ [fs write:data];
430
+ free(bytes);
431
+ callback(@[[NSNull null]]);
432
+ }
433
+
434
+ #pragma mark - fs.writeChunk
435
+ RCT_EXPORT_METHOD(writeChunk:(NSString *)streamId
436
+ withData:(NSString *)data
437
+ callback:(RCTResponseSenderBlock) callback)
438
+ {
439
+ ReactNativeBlobUtilFS *fs = [[ReactNativeBlobUtilFS getFileStreams] valueForKey:streamId];
440
+ [fs writeEncodeChunk:data];
441
+ callback(@[[NSNull null]]);
442
+ }
443
+
444
+ #pragma mark - fs.closeStream
445
+ RCT_EXPORT_METHOD(closeStream:(NSString *)streamId callback:(RCTResponseSenderBlock) callback)
446
+ {
447
+ ReactNativeBlobUtilFS *fs = [[ReactNativeBlobUtilFS getFileStreams] valueForKey:streamId];
448
+ [fs closeOutStream];
449
+ callback(@[[NSNull null], @YES]);
450
+ }
451
+
452
+ #pragma mark - unlink
453
+ RCT_EXPORT_METHOD(unlink:(NSString *)path callback:(RCTResponseSenderBlock) callback)
454
+ {
455
+ NSError * error = nil;
456
+ [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
457
+ if(error == nil || [[NSFileManager defaultManager] fileExistsAtPath:path] == NO)
458
+ callback(@[[NSNull null]]);
459
+ else
460
+ callback(@[[NSString stringWithFormat:@"failed to unlink file or path at %@", path]]);
461
+ }
462
+
463
+ #pragma mark - fs.removeSession
464
+ RCT_EXPORT_METHOD(removeSession:(NSArray *)paths callback:(RCTResponseSenderBlock) callback)
465
+ {
466
+ NSError * error = nil;
467
+
468
+ for(NSString * path in paths) {
469
+ [[NSFileManager defaultManager] removeItemAtPath:path error:&error];
470
+ if(error != nil) {
471
+ callback(@[[NSString stringWithFormat:@"failed to remove session path at %@", path]]);
472
+ return;
473
+ }
474
+ }
475
+ callback(@[[NSNull null]]);
476
+
477
+ }
478
+
479
+ #pragma mark - fs.ls
480
+ // Signature for the Old Architecture
481
+ RCT_EXPORT_METHOD(ls:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
482
+ {
483
+ [self ls:path resolve:resolve reject:reject];
484
+ }
485
+
486
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
487
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
488
+ - (void)ls:(NSString *)path
489
+ resolve:(RCTPromiseResolveBlock)resolve
490
+ reject:(RCTPromiseRejectBlock)reject
491
+ {
492
+ NSFileManager* fm = [NSFileManager defaultManager];
493
+ BOOL exist = NO;
494
+ BOOL isDir = NO;
495
+ exist = [fm fileExistsAtPath:path isDirectory:&isDir];
496
+ if(exist == NO) {
497
+ return reject(@"ENOENT", [NSString stringWithFormat:@"No such file '%@'", path], nil);
498
+ }
499
+ if(isDir == NO) {
500
+ return reject(@"ENOTDIR", [NSString stringWithFormat:@"Not a directory '%@'", path], nil);
501
+ }
502
+ NSError * error = nil;
503
+ NSArray * result = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
504
+
505
+ if(error == nil)
506
+ resolve(result);
507
+ else
508
+ reject(@"EUNSPECIFIED", [error description], nil);
509
+ }
510
+
511
+ #pragma mark - fs.stat
512
+ RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) callback)
513
+ {
514
+
515
+ [ReactNativeBlobUtilFS getPathFromUri:target completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
516
+ __block NSMutableDictionary * result;
517
+ if(path != nil)
518
+ {
519
+ NSFileManager* fm = [NSFileManager defaultManager];
520
+ BOOL exist = NO;
521
+ BOOL isDir = NO;
522
+ NSError * error = nil;
523
+
524
+ exist = [fm fileExistsAtPath:path isDirectory:&isDir];
525
+ if(exist == NO) {
526
+ callback(@[[NSString stringWithFormat:@"failed to stat path `%@` because it does not exist or it is not a folder", path]]);
527
+ return ;
528
+ }
529
+ result = [ReactNativeBlobUtilFS stat:path error:&error].mutableCopy;
530
+
531
+ if(error == nil)
532
+ callback(@[[NSNull null], result]);
533
+ else
534
+ callback(@[[error localizedDescription], [NSNull null]]);
535
+
536
+ }
537
+ else if(asset != nil)
538
+ {
539
+ __block NSNumber * size = [NSNumber numberWithLong:[asset size]];
540
+ result = [asset metadata];
541
+ [result setValue:size forKey:@"size"];
542
+ callback(@[[NSNull null], result]);
543
+ }
544
+ else
545
+ {
546
+ callback(@[@"failed to stat path, could not resolve URI", [NSNull null]]);
547
+ }
548
+ }];
549
+ }
550
+
551
+ #pragma mark - fs.lstat
552
+ RCT_EXPORT_METHOD(lstat:(NSString *)path callback:(RCTResponseSenderBlock) callback)
553
+ {
554
+ NSFileManager* fm = [NSFileManager defaultManager];
555
+ BOOL exist = NO;
556
+ BOOL isDir = NO;
557
+
558
+ path = [ReactNativeBlobUtilFS getPathOfAsset:path];
559
+
560
+ exist = [fm fileExistsAtPath:path isDirectory:&isDir];
561
+ if(exist == NO) {
562
+ callback(@[[NSString stringWithFormat:@"failed to lstat path `%@` because it does not exist or it is not a folder", path]]);
563
+ return ;
564
+ }
565
+ NSError * error = nil;
566
+ NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
567
+
568
+ NSMutableArray * res = [[NSMutableArray alloc] init];
569
+ if(isDir == YES) {
570
+ for(NSString * p in files) {
571
+ NSString * filePath = [NSString stringWithFormat:@"%@/%@", path, p];
572
+ [res addObject:[ReactNativeBlobUtilFS stat:filePath error:&error]];
573
+ }
574
+ }
575
+ else {
576
+ [res addObject:[ReactNativeBlobUtilFS stat:path error:&error]];
577
+ }
578
+
579
+ if(error == nil)
580
+ callback(@[[NSNull null], res == nil ? [NSNull null] :res ]);
581
+ else
582
+ callback(@[[error localizedDescription], [NSNull null]]);
583
+
584
+ }
585
+
586
+ #pragma mark - fs.cp
587
+ // Signature for the Old Architecture
588
+ RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
589
+ {
590
+ [self cp:src dest:dest callback:callback];
591
+ }
592
+
593
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
594
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
595
+ - (void)cp:(NSString *)src
596
+ dest:(NSString *)dest
597
+ callback:(RCTResponseSenderBlock)callback
598
+ {
599
+ // path = [ReactNativeBlobUtilFS getPathOfAsset:path];
600
+ [ReactNativeBlobUtilFS getPathFromUri:src completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
601
+ NSError * error = nil;
602
+ if(path == nil)
603
+ {
604
+ [ReactNativeBlobUtilFS writeAssetToPath:asset dest:dest];
605
+ callback(@[[NSNull null], @YES]);
606
+ }
607
+ else
608
+ {
609
+ // If the destination exists there will be an error
610
+ BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
611
+
612
+ if(error == nil)
613
+ callback(@[[NSNull null], @YES]);
614
+ else
615
+ callback(@[[error localizedDescription], @NO]);
616
+ }
617
+ }];
618
+ }
619
+
620
+ #pragma mark - fs.mv
621
+ // Signature for the Old Architecture
622
+ RCT_EXPORT_METHOD(mv:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
623
+ {
624
+ [self mv:path dest:dest callback:callback];
625
+ }
626
+
627
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
628
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
629
+ - (void)mv:(NSString *)path
630
+ dest:(NSString *)dest
631
+ callback:(RCTResponseSenderBlock)callback
632
+ {
633
+ NSError * error = nil;
634
+ BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
635
+
636
+ if(error == nil)
637
+ callback(@[[NSNull null], @YES]);
638
+ else
639
+ callback(@[[error localizedDescription], @NO]);
640
+
641
+ }
642
+
643
+ #pragma mark - fs.mkdir
644
+ RCT_EXPORT_METHOD(mkdir:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
645
+ {
646
+ [self mkdir:path resolve:resolve reject:reject];
647
+ }
648
+
649
+ - (void)mkdir:(NSString *)path
650
+ resolve:(RCTPromiseResolveBlock)resolve
651
+ reject:(RCTPromiseRejectBlock)reject
652
+ {
653
+ [ReactNativeBlobUtilFS mkdir:path resolver:resolve rejecter:reject];
654
+ }
655
+
656
+ #pragma mark - fs.readFile
657
+ // Signature for the Old Architecture
658
+ RCT_EXPORT_METHOD(readFile:(NSString *)path
659
+ encoding:(NSString *)encoding
660
+ transformFile:(BOOL) transformFile
661
+ resolver:(RCTPromiseResolveBlock)resolve
662
+ rejecter:(RCTPromiseRejectBlock)reject)
663
+ {
664
+ [self readFile:path encoding:encoding transformFile:transformFile resolve:resolve reject:reject];
665
+ }
666
+
667
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
668
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
669
+ - (void)readFile:(NSString *)path
670
+ encoding:(NSString *)encoding
671
+ transformFile:(BOOL)transformFile
672
+ resolve:(RCTPromiseResolveBlock)resolve
673
+ reject:(RCTPromiseRejectBlock)reject
674
+ {
675
+
676
+ [ReactNativeBlobUtilFS readFile:path encoding:encoding transformFile:transformFile onComplete:^(NSData * content, NSString * code, NSString * err) {
677
+ if(err != nil) {
678
+ reject(code, err, nil);
679
+ return;
680
+ }
681
+ if([encoding isEqualToString:@"ascii"]) {
682
+ resolve((NSMutableArray *)content);
683
+ }
684
+ if([encoding isEqualToString:@"base64"]) {
685
+ resolve([content base64EncodedStringWithOptions:0]);
686
+ } else {
687
+ resolve([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]);
688
+ }
689
+ }];
690
+ }
691
+
692
+ #pragma mark - fs.hash
693
+ // Signature for the Old Architecture
694
+ RCT_EXPORT_METHOD(hash:(NSString *)path
695
+ algorithm:(NSString *)algorithm
696
+ resolver:(RCTPromiseResolveBlock)resolve
697
+ rejecter:(RCTPromiseRejectBlock)reject)
698
+ {
699
+ [self hash:path algorithm:algorithm resolve:resolve reject:reject];
700
+ }
701
+
702
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
703
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
704
+ - (void)hash:(NSString *)path
705
+ algorithm:(NSString *)algorithm
706
+ resolve:(RCTPromiseResolveBlock)resolve
707
+ reject:(RCTPromiseRejectBlock)reject
708
+ {
709
+ [ReactNativeBlobUtilFS hash:path algorithm:[NSString stringWithString:algorithm] resolver:resolve rejecter:reject];
710
+ }
711
+
712
+ #pragma mark - fs.readStream
713
+ RCT_EXPORT_METHOD(readStream:(NSString *)path encoding:(NSString *)encoding bufferSize:(int)bufferSize tick:(int)tick streamId:(NSString *)streamId)
714
+ {
715
+ if(bufferSize == 0) {
716
+ if([[encoding lowercaseString] isEqualToString:@"base64"])
717
+ bufferSize = 4095;
718
+ else
719
+ bufferSize = 4096;
720
+ }
721
+
722
+ dispatch_async(fsQueue, ^{
723
+ [ReactNativeBlobUtilFS readStream:path encoding:encoding bufferSize:bufferSize tick:tick streamId:streamId baseModule:self];
724
+ });
725
+ }
726
+
727
+ #pragma mark - fs.getEnvironmentDirs
728
+ RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback)
729
+ {
730
+
731
+ callback(@[
732
+ [ReactNativeBlobUtilFS getDocumentDir],
733
+ [ReactNativeBlobUtilFS getCacheDir],
734
+ ]);
735
+ }
736
+
737
+ #pragma mark - net.cancelRequest
738
+ RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBlock)callback) {
739
+ [[ReactNativeBlobUtilNetwork sharedInstance] cancelRequest:taskId];
740
+ callback(@[[NSNull null], taskId]);
741
+
742
+ }
743
+
744
+ #pragma mark - net.enableProgressReport
745
+ RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
746
+ {
747
+
748
+ ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Download interval:interval count:count];
749
+ [[ReactNativeBlobUtilNetwork sharedInstance] enableProgressReport:taskId config:cfg];
750
+ }
751
+
752
+ #pragma mark - net.enableUploadProgressReport
753
+ RCT_EXPORT_METHOD(enableUploadProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
754
+ {
755
+ ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Upload interval:interval count:count];
756
+ [[ReactNativeBlobUtilNetwork sharedInstance] enableUploadProgress:taskId config:cfg];
757
+ }
758
+
759
+ #pragma mark - fs.slice
760
+ // Signature for the Old Architecture
761
+ RCT_EXPORT_METHOD(slice:(NSString *)src dest:(NSString *)dest start:(nonnull NSNumber *)start end:(nonnull NSNumber *)end resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
762
+ {
763
+ [self slice:src dest:dest start:start.doubleValue end:end.doubleValue resolve:resolve reject:reject];
764
+ }
765
+
766
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
767
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
768
+ - (void)slice:(NSString *)src
769
+ dest:(NSString *)dest
770
+ start:(double)start
771
+ end:(double)end
772
+ resolve:(RCTPromiseResolveBlock)resolve
773
+ reject:(RCTPromiseRejectBlock)reject
774
+ {
775
+ [ReactNativeBlobUtilFS slice:src dest:dest start:@(start) end:@(end) encode:@"" resolver:resolve rejecter:reject];
776
+ }
777
+
778
+ // Signature for the Old Architecture
779
+ RCT_EXPORT_METHOD(presentOptionsMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
780
+ {
781
+ [self presentOptionsMenu:uri scheme:scheme resolve:resolve reject:reject];
782
+ }
783
+
784
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
785
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
786
+ - (void)presentOptionsMenu:(NSString *)uri
787
+ scheme:(NSString *)scheme
788
+ resolve:(RCTPromiseResolveBlock)resolve
789
+ reject:(RCTPromiseRejectBlock)reject
790
+ {
791
+ NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
792
+ NSURL * url = [[NSURL alloc] initWithString:utf8uri];
793
+ // NSURL * url = [[NSURL alloc] initWithString:uri];
794
+ documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
795
+ UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
796
+ documentController.delegate = self;
797
+ if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
798
+ CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
799
+ dispatch_sync(dispatch_get_main_queue(), ^{
800
+ [documentController presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES];
801
+ });
802
+ resolve(@[[NSNull null]]);
803
+ } else {
804
+ reject(@"EINVAL", @"scheme is not supported", nil);
805
+ }
806
+ }
807
+
808
+ // Signature for the Old Architecture
809
+ RCT_EXPORT_METHOD(presentOpenInMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
810
+ {
811
+ [self presentOpenInMenu:uri scheme:scheme resolve:resolve reject:reject];
812
+ }
813
+
814
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
815
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
816
+ - (void)presentOpenInMenu:(NSString *)uri
817
+ scheme:(NSString *)scheme
818
+ resolve:(RCTPromiseResolveBlock)resolve
819
+ reject:(RCTPromiseRejectBlock)reject
820
+ {
821
+ NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
822
+ NSURL * url = [[NSURL alloc] initWithString:utf8uri];
823
+ documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
824
+ UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
825
+ documentController.delegate = self;
826
+ if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
827
+ CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
828
+ dispatch_sync(dispatch_get_main_queue(), ^{
829
+ [documentController presentOpenInMenuFromRect:rect inView:rootCtrl.view animated:YES];
830
+ });
831
+ resolve(@[[NSNull null]]);
832
+ } else {
833
+ reject(@"EINVAL", @"scheme is not supported", nil);
834
+ }
835
+ }
836
+
837
+ # pragma mark - open file with UIDocumentInteractionController and delegate
838
+ // Signature for the Old Architecture
839
+ RCT_EXPORT_METHOD(presentPreview:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
840
+ {
841
+ [self presentPreview:uri scheme:scheme resolve:resolve reject:reject];
842
+ }
843
+
844
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
845
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
846
+ - (void)presentPreview:(NSString *)uri
847
+ scheme:(NSString *)scheme
848
+ resolve:(RCTPromiseResolveBlock)resolve
849
+ reject:(RCTPromiseRejectBlock)reject
850
+ {
851
+ NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
852
+ NSURL * url = [[NSURL alloc] initWithString:utf8uri];
853
+ // NSURL * url = [[NSURL alloc] initWithString:uri];
854
+ documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
855
+ documentController.delegate = self;
856
+
857
+ if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
858
+ dispatch_sync(dispatch_get_main_queue(), ^{
859
+ if([documentController presentPreviewAnimated:YES]) {
860
+ resolve(@[[NSNull null]]);
861
+ } else {
862
+ reject(@"EINVAL", @"document is not supported", nil);
863
+ }
864
+ });
865
+ } else {
866
+ reject(@"EINVAL", @"scheme is not supported", nil);
867
+ }
868
+ }
869
+
870
+ # pragma mark - exclude from backup key
871
+
872
+ RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
873
+ {
874
+ [self excludeFromBackupKey:url resolve:resolve reject:reject];
875
+ }
876
+
877
+ - (void)excludeFromBackupKey:(NSString *)url
878
+ resolve:(RCTPromiseResolveBlock)resolve
879
+ reject:(RCTPromiseRejectBlock)reject
880
+ {
881
+ NSError *error = nil;
882
+ [ [NSURL URLWithString:url] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
883
+ if(!error)
884
+ {
885
+ resolve(@[[NSNull null]]);
886
+ } else {
887
+ reject(@"EUNSPECIFIED", [error description], nil);
888
+ }
889
+
890
+ }
891
+
892
+
893
+ RCT_EXPORT_METHOD(df:(RCTResponseSenderBlock)callback)
894
+ {
895
+ [ReactNativeBlobUtilFS df:callback];
896
+ }
897
+
898
+ - (UIViewController *)documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
899
+ {
900
+ UIWindow *window = [UIApplication sharedApplication].keyWindow;
901
+ return window.rootViewController;
902
+ }
903
+
904
+ # pragma mark - Android Only methods
905
+ // These methods are required because in the New Arch we have a single spec for both platforms
906
+ - (void)actionViewIntent:(NSString *) path
907
+ mime:(NSString *) mime
908
+ chooserTitle:(NSString *) chooserTitle
909
+ resolve:(RCTPromiseResolveBlock)resolve
910
+ reject:(RCTPromiseRejectBlock)reject
911
+ {
912
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
913
+ }
914
+
915
+ - (void)addCompleteDownload:(NSDictionary *)config
916
+ resolve:(RCTPromiseResolveBlock)resolve
917
+ reject:(RCTPromiseRejectBlock)reject
918
+ {
919
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
920
+ }
921
+
922
+ - (void)copyToInternal:(NSString *)contentUri
923
+ destpath:(NSString *) destpath
924
+ resolve:(RCTPromiseResolveBlock)resolve
925
+ reject:(RCTPromiseRejectBlock)reject
926
+ {
927
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
928
+ }
929
+ - (void)copyToMediaStore:(NSDictionary *)filedata
930
+ mt:(NSString *) mt
931
+ path:(NSString *) path
932
+ resolve:(RCTPromiseResolveBlock)resolve
933
+ reject:(RCTPromiseRejectBlock)reject
934
+ {
935
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
936
+ }
937
+
938
+ - (void)createMediaFile:(NSDictionary *)filedata
939
+ mt:(NSString *) mt
940
+ resolve:(RCTPromiseResolveBlock)resolve
941
+ reject:(RCTPromiseRejectBlock)reject
942
+ {
943
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
944
+ }
945
+
946
+ - (void)getBlob:(NSString *)contentUri
947
+ encoding:(NSString *)encoding
948
+ resolve:(RCTPromiseResolveBlock)resolve
949
+ reject:(RCTPromiseRejectBlock)reject
950
+ {
951
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
952
+ }
953
+
954
+ - (void)getContentIntent:(NSString *)mime
955
+ resolve:(RCTPromiseResolveBlock)resolve
956
+ reject:(RCTPromiseRejectBlock)reject
957
+ {
958
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
959
+ }
960
+ - (void)getSDCardDir:(RCTPromiseResolveBlock)resolve
961
+ reject:(RCTPromiseRejectBlock)reject
962
+ {
963
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
964
+ }
965
+ - (void)getSDCardApplicationDir:(RCTPromiseResolveBlock)resolve
966
+ reject:(RCTPromiseRejectBlock)reject
967
+ {
968
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
969
+ }
970
+ - (void)scanFile:(NSArray *)pairs
971
+ callback:(RCTResponseSenderBlock)callback
972
+ {
973
+ callback(@[@"Scan file method not supported in iOS"]);
974
+ }
975
+ - (void)writeToMediaFile:(NSString *)fileUri
976
+ path:(NSString *)path
977
+ transformFile:(BOOL)transformFile
978
+ resolve:(RCTPromiseResolveBlock)resolve
979
+ reject:(RCTPromiseRejectBlock)reject
980
+ {
981
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
982
+ }
983
+
984
+ # pragma mark - New Architecture
985
+ #if RCT_NEW_ARCH_ENABLED
986
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
987
+ (const facebook::react::ObjCTurboModule::InitParams &)params
988
+ {
989
+ return std::make_shared<facebook::react::NativeBlobUtilsSpecJSI>(params);
990
+ }
991
+ #endif
992
+
993
+ @end