react-native-blob-util 0.24.6 → 0.24.8

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 (98) hide show
  1. package/.eslintrc.json +96 -96
  2. package/LICENSE +21 -21
  3. package/Migration.md +41 -41
  4. package/NuGet.config +11 -11
  5. package/README.md +1109 -1109
  6. package/android/gradle.properties +1 -1
  7. package/android/src/main/AndroidManifest.xml +37 -37
  8. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConfig.java +59 -59
  9. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilConst.java +20 -20
  10. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilFileTransformer.java +9 -9
  11. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilImpl.java +431 -431
  12. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilProgressConfig.java +39 -39
  13. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilReq.java +1092 -1092
  14. package/android/src/main/java/com/ReactNativeBlobUtil/ReactNativeBlobUtilStream.java +48 -43
  15. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilDefaultResp.java +98 -98
  16. package/android/src/main/java/com/ReactNativeBlobUtil/Response/ReactNativeBlobUtilFileResp.java +183 -166
  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.js +58 -58
  25. package/class/ReactNativeBlobUtilCanceledFetchError.js +9 -9
  26. package/class/ReactNativeBlobUtilFile.js +5 -5
  27. package/class/ReactNativeBlobUtilSession.js +68 -68
  28. package/class/ReactNativeBlobUtilWriteStream.js +50 -50
  29. package/class/StatefulPromise.js +7 -7
  30. package/codegenSpecs/NativeBlobUtils.js +86 -86
  31. package/components/Fetch.onPress.js +10 -10
  32. package/components/Fetch.when.js +15 -15
  33. package/fetch.js +350 -350
  34. package/fs.js +480 -480
  35. package/index.d.ts +881 -881
  36. package/index.js +64 -64
  37. package/index.js.flow +192 -192
  38. package/index.web.js +1 -1
  39. package/ios/PrivacyInfo.xcprivacy +28 -28
  40. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.h +55 -55
  41. package/ios/ReactNativeBlobUtil/ReactNativeBlobUtil.mm +1013 -1013
  42. package/ios/ReactNativeBlobUtil.xcodeproj/project.pbxproj +405 -405
  43. package/ios/ReactNativeBlobUtilConst.h +58 -58
  44. package/ios/ReactNativeBlobUtilConst.mm +47 -47
  45. package/ios/ReactNativeBlobUtilFS.h +108 -108
  46. package/ios/ReactNativeBlobUtilFS.mm +1080 -1080
  47. package/ios/ReactNativeBlobUtilFileTransformer.h +23 -23
  48. package/ios/ReactNativeBlobUtilFileTransformer.mm +20 -20
  49. package/ios/ReactNativeBlobUtilNetwork.h +50 -49
  50. package/ios/ReactNativeBlobUtilNetwork.mm +173 -159
  51. package/ios/ReactNativeBlobUtilProgress.h +32 -32
  52. package/ios/ReactNativeBlobUtilProgress.mm +57 -57
  53. package/ios/ReactNativeBlobUtilReqBuilder.h +37 -37
  54. package/ios/ReactNativeBlobUtilReqBuilder.mm +292 -292
  55. package/ios/ReactNativeBlobUtilRequest.h +48 -48
  56. package/ios/ReactNativeBlobUtilRequest.mm +586 -584
  57. package/ios.js +61 -61
  58. package/json-stream.js +42 -42
  59. package/lib/oboe-browser.js +2703 -2703
  60. package/mediacollection.js +36 -36
  61. package/package.json +86 -77
  62. package/polyfill/Blob.js +362 -362
  63. package/polyfill/Event.js +11 -11
  64. package/polyfill/EventTarget.js +78 -78
  65. package/polyfill/Fetch.js +219 -219
  66. package/polyfill/File.js +27 -27
  67. package/polyfill/FileReader.js +91 -91
  68. package/polyfill/ProgressEvent.js +32 -32
  69. package/polyfill/XMLHttpRequest.js +466 -466
  70. package/polyfill/XMLHttpRequestEventTarget.js +126 -126
  71. package/polyfill/index.js +11 -11
  72. package/react-native-blob-util.podspec +48 -48
  73. package/types.js +69 -69
  74. package/utils/log.js +40 -40
  75. package/utils/unicode.js +7 -7
  76. package/utils/uri.js +33 -33
  77. package/utils/uuid.js +5 -4
  78. package/windows/ExperimentalFeatures.props +33 -33
  79. package/windows/README.md +2 -2
  80. package/windows/ReactNativeBlobUtil/PropertySheet.props +15 -15
  81. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.cpp +1836 -1836
  82. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.def +3 -3
  83. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.h +372 -372
  84. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj +139 -139
  85. package/windows/ReactNativeBlobUtil/ReactNativeBlobUtil.vcxproj.filters +43 -43
  86. package/windows/ReactNativeBlobUtil/ReactPackageProvider.cpp +20 -20
  87. package/windows/ReactNativeBlobUtil/ReactPackageProvider.h +24 -24
  88. package/windows/ReactNativeBlobUtil/ReactPackageProvider.idl +9 -9
  89. package/windows/ReactNativeBlobUtil/codegen/.clang-format +1 -1
  90. package/windows/ReactNativeBlobUtil/codegen/NativeBlobUtilsDataTypes.g.h +42 -42
  91. package/windows/ReactNativeBlobUtil/codegen/NativeBlobUtilsSpec.g.h +353 -353
  92. package/windows/ReactNativeBlobUtil/packages.config +3 -3
  93. package/windows/ReactNativeBlobUtil/packages.lock.json +59 -59
  94. package/windows/ReactNativeBlobUtil/pch.cpp +1 -1
  95. package/windows/ReactNativeBlobUtil/pch.h +30 -30
  96. package/windows/ReactNativeBlobUtil/resource.h +5 -5
  97. package/windows/ReactNativeBlobUtil/targetver.h +8 -8
  98. package/windows/ReactNativeBlobUtil.sln +43 -43
@@ -1,1013 +1,1013 @@
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, PHAsset *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
- // For PHAsset, get basic metadata
540
- NSMutableDictionary *assetInfo = [NSMutableDictionary dictionary];
541
- [assetInfo setValue:[NSNumber numberWithLong:asset.pixelWidth] forKey:@"width"];
542
- [assetInfo setValue:[NSNumber numberWithLong:asset.pixelHeight] forKey:@"height"];
543
- [assetInfo setValue:[NSNumber numberWithLong:asset.duration] forKey:@"duration"];
544
- [assetInfo setValue:[NSDate date] forKey:@"lastModified"];
545
- [assetInfo setValue:@"asset" forKey:@"type"];
546
- [assetInfo setValue:@"PHAsset" forKey:@"filename"];
547
-
548
- // Get actual file size by requesting image data
549
- PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
550
- options.synchronous = YES;
551
- options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
552
- options.resizeMode = PHImageRequestOptionsResizeModeNone;
553
-
554
- [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
555
- if (imageData) {
556
- [assetInfo setValue:[NSNumber numberWithLong:imageData.length] forKey:@"size"];
557
- } else {
558
- [assetInfo setValue:[NSNumber numberWithLong:0] forKey:@"size"];
559
- }
560
- callback(@[[NSNull null], assetInfo]);
561
- }];
562
- }
563
- else
564
- {
565
- callback(@[@"failed to stat path, could not resolve URI", [NSNull null]]);
566
- }
567
- }];
568
- }
569
-
570
- #pragma mark - fs.lstat
571
- RCT_EXPORT_METHOD(lstat:(NSString *)path callback:(RCTResponseSenderBlock) callback)
572
- {
573
- NSFileManager* fm = [NSFileManager defaultManager];
574
- BOOL exist = NO;
575
- BOOL isDir = NO;
576
-
577
- path = [ReactNativeBlobUtilFS getPathOfAsset:path];
578
-
579
- exist = [fm fileExistsAtPath:path isDirectory:&isDir];
580
- if(exist == NO) {
581
- callback(@[[NSString stringWithFormat:@"failed to lstat path `%@` because it does not exist or it is not a folder", path]]);
582
- return ;
583
- }
584
- NSError * error = nil;
585
- NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
586
-
587
- NSMutableArray * res = [[NSMutableArray alloc] init];
588
- if(isDir == YES) {
589
- for(NSString * p in files) {
590
- NSString * filePath = [NSString stringWithFormat:@"%@/%@", path, p];
591
- [res addObject:[ReactNativeBlobUtilFS stat:filePath error:&error]];
592
- }
593
- }
594
- else {
595
- [res addObject:[ReactNativeBlobUtilFS stat:path error:&error]];
596
- }
597
-
598
- if(error == nil)
599
- callback(@[[NSNull null], res == nil ? [NSNull null] :res ]);
600
- else
601
- callback(@[[error localizedDescription], [NSNull null]]);
602
-
603
- }
604
-
605
- #pragma mark - fs.cp
606
- // Signature for the Old Architecture
607
- RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
608
- {
609
- [self cp:src dest:dest callback:callback];
610
- }
611
-
612
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
613
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
614
- - (void)cp:(NSString *)src
615
- dest:(NSString *)dest
616
- callback:(RCTResponseSenderBlock)callback
617
- {
618
- // path = [ReactNativeBlobUtilFS getPathOfAsset:path];
619
- [ReactNativeBlobUtilFS getPathFromUri:src completionHandler:^(NSString *path, PHAsset *asset) {
620
- NSError * error = nil;
621
- if(path == nil)
622
- {
623
- [ReactNativeBlobUtilFS writeAssetToPath:asset dest:dest];
624
- callback(@[[NSNull null], @YES]);
625
- }
626
- else
627
- {
628
- // If the destination exists there will be an error
629
- BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
630
-
631
- if(error == nil)
632
- callback(@[[NSNull null], @YES]);
633
- else
634
- callback(@[[error localizedDescription], @NO]);
635
- }
636
- }];
637
- }
638
-
639
- #pragma mark - fs.mv
640
- // Signature for the Old Architecture
641
- RCT_EXPORT_METHOD(mv:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
642
- {
643
- [self mv:path dest:dest callback:callback];
644
- }
645
-
646
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
647
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
648
- - (void)mv:(NSString *)path
649
- dest:(NSString *)dest
650
- callback:(RCTResponseSenderBlock)callback
651
- {
652
- NSError * error = nil;
653
- BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
654
-
655
- if(error == nil)
656
- callback(@[[NSNull null], @YES]);
657
- else
658
- callback(@[[error localizedDescription], @NO]);
659
-
660
- }
661
-
662
- #pragma mark - fs.mkdir
663
- RCT_EXPORT_METHOD(mkdir:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
664
- {
665
- [self mkdir:path resolve:resolve reject:reject];
666
- }
667
-
668
- - (void)mkdir:(NSString *)path
669
- resolve:(RCTPromiseResolveBlock)resolve
670
- reject:(RCTPromiseRejectBlock)reject
671
- {
672
- [ReactNativeBlobUtilFS mkdir:path resolver:resolve rejecter:reject];
673
- }
674
-
675
- #pragma mark - fs.readFile
676
- // Signature for the Old Architecture
677
- RCT_EXPORT_METHOD(readFile:(NSString *)path
678
- encoding:(NSString *)encoding
679
- transformFile:(BOOL) transformFile
680
- resolver:(RCTPromiseResolveBlock)resolve
681
- rejecter:(RCTPromiseRejectBlock)reject)
682
- {
683
- [self readFile:path encoding:encoding transformFile:transformFile resolve:resolve reject:reject];
684
- }
685
-
686
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
687
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
688
- - (void)readFile:(NSString *)path
689
- encoding:(NSString *)encoding
690
- transformFile:(BOOL)transformFile
691
- resolve:(RCTPromiseResolveBlock)resolve
692
- reject:(RCTPromiseRejectBlock)reject
693
- {
694
-
695
- [ReactNativeBlobUtilFS readFile:path encoding:encoding transformFile:transformFile onComplete:^(NSData * content, NSString * code, NSString * err) {
696
- if(err != nil) {
697
- reject(code, err, nil);
698
- return;
699
- }
700
- if([encoding isEqualToString:@"ascii"]) {
701
- resolve((NSMutableArray *)content);
702
- } else if([encoding isEqualToString:@"base64"]) {
703
- resolve([content base64EncodedStringWithOptions:0]);
704
- } else {
705
- resolve([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]);
706
- }
707
- }];
708
- }
709
-
710
- #pragma mark - fs.hash
711
- // Signature for the Old Architecture
712
- RCT_EXPORT_METHOD(hash:(NSString *)path
713
- algorithm:(NSString *)algorithm
714
- resolver:(RCTPromiseResolveBlock)resolve
715
- rejecter:(RCTPromiseRejectBlock)reject)
716
- {
717
- [self hash:path algorithm:algorithm resolve:resolve reject:reject];
718
- }
719
-
720
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
721
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
722
- - (void)hash:(NSString *)path
723
- algorithm:(NSString *)algorithm
724
- resolve:(RCTPromiseResolveBlock)resolve
725
- reject:(RCTPromiseRejectBlock)reject
726
- {
727
- [ReactNativeBlobUtilFS hash:path algorithm:[NSString stringWithString:algorithm] resolver:resolve rejecter:reject];
728
- }
729
-
730
- #pragma mark - fs.readStream
731
- RCT_EXPORT_METHOD(readStream:(NSString *)path encoding:(NSString *)encoding bufferSize:(double)bufferSize tick:(double)tick streamId:(NSString *)streamId)
732
- {
733
- if(bufferSize == 0) {
734
- if([[encoding lowercaseString] isEqualToString:@"base64"])
735
- bufferSize = 4095;
736
- else
737
- bufferSize = 4096;
738
- }
739
-
740
- dispatch_async(fsQueue, ^{
741
- [ReactNativeBlobUtilFS readStream:path encoding:encoding bufferSize:bufferSize tick:tick streamId:streamId baseModule:self];
742
- });
743
- }
744
-
745
- #pragma mark - fs.getEnvironmentDirs
746
- RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback)
747
- {
748
-
749
- callback(@[
750
- [ReactNativeBlobUtilFS getDocumentDir],
751
- [ReactNativeBlobUtilFS getCacheDir],
752
- ]);
753
- }
754
-
755
- #pragma mark - net.cancelRequest
756
- RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBlock)callback) {
757
- [[ReactNativeBlobUtilNetwork sharedInstance] cancelRequest:taskId];
758
- callback(@[[NSNull null], taskId]);
759
-
760
- }
761
-
762
- #pragma mark - net.enableProgressReport
763
- RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(double)interval count:(double)count)
764
- {
765
- NSNumber *intervalNumber = [NSNumber numberWithDouble:interval];
766
- NSNumber *countNumber = [NSNumber numberWithInteger:count];
767
-
768
- ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Download interval:intervalNumber count:countNumber];
769
- [[ReactNativeBlobUtilNetwork sharedInstance] enableProgressReport:taskId config:cfg];
770
- }
771
-
772
- #pragma mark - net.enableUploadProgressReport
773
- RCT_EXPORT_METHOD(enableUploadProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
774
- {
775
- ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Upload interval:interval count:count];
776
- [[ReactNativeBlobUtilNetwork sharedInstance] enableUploadProgress:taskId config:cfg];
777
- }
778
-
779
- #pragma mark - fs.slice
780
- // Signature for the Old Architecture
781
- RCT_EXPORT_METHOD(slice:(NSString *)src dest:(NSString *)dest start:(nonnull NSNumber *)start end:(nonnull NSNumber *)end resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
782
- {
783
- [self slice:src dest:dest start:start.doubleValue end:end.doubleValue resolve:resolve reject:reject];
784
- }
785
-
786
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
787
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
788
- - (void)slice:(NSString *)src
789
- dest:(NSString *)dest
790
- start:(double)start
791
- end:(double)end
792
- resolve:(RCTPromiseResolveBlock)resolve
793
- reject:(RCTPromiseRejectBlock)reject
794
- {
795
- [ReactNativeBlobUtilFS slice:src dest:dest start:@(start) end:@(end) encode:@"" resolver:resolve rejecter:reject];
796
- }
797
-
798
- // Signature for the Old Architecture
799
- RCT_EXPORT_METHOD(presentOptionsMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
800
- {
801
- [self presentOptionsMenu:uri scheme:scheme resolve:resolve reject:reject];
802
- }
803
-
804
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
805
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
806
- - (void)presentOptionsMenu:(NSString *)uri
807
- scheme:(NSString *)scheme
808
- resolve:(RCTPromiseResolveBlock)resolve
809
- reject:(RCTPromiseRejectBlock)reject
810
- {
811
- NSString * utf8uri = [uri stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
812
- NSURL * url = [[NSURL alloc] initWithString:utf8uri];
813
- // NSURL * url = [[NSURL alloc] initWithString:uri];
814
- documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
815
- UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
816
- documentController.delegate = self;
817
- if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
818
- CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
819
- dispatch_sync(dispatch_get_main_queue(), ^{
820
- [documentController presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES];
821
- });
822
- resolve(@[[NSNull null]]);
823
- } else {
824
- reject(@"EINVAL", @"scheme is not supported", nil);
825
- }
826
- }
827
-
828
- // Signature for the Old Architecture
829
- RCT_EXPORT_METHOD(presentOpenInMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
830
- {
831
- [self presentOpenInMenu:uri scheme:scheme resolve:resolve reject:reject];
832
- }
833
-
834
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
835
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
836
- - (void)presentOpenInMenu:(NSString *)uri
837
- scheme:(NSString *)scheme
838
- resolve:(RCTPromiseResolveBlock)resolve
839
- reject:(RCTPromiseRejectBlock)reject
840
- {
841
- NSString * utf8uri = [uri stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
842
- NSURL * url = [[NSURL alloc] initWithString:utf8uri];
843
- documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
844
- UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
845
- documentController.delegate = self;
846
- if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
847
- CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
848
- dispatch_sync(dispatch_get_main_queue(), ^{
849
- [documentController presentOpenInMenuFromRect:rect inView:rootCtrl.view animated:YES];
850
- });
851
- resolve(@[[NSNull null]]);
852
- } else {
853
- reject(@"EINVAL", @"scheme is not supported", nil);
854
- }
855
- }
856
-
857
- # pragma mark - open file with UIDocumentInteractionController and delegate
858
- // Signature for the Old Architecture
859
- RCT_EXPORT_METHOD(presentPreview:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
860
- {
861
- [self presentPreview:uri scheme:scheme resolve:resolve reject:reject];
862
- }
863
-
864
- // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
865
- // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
866
- - (void)presentPreview:(NSString *)uri
867
- scheme:(NSString *)scheme
868
- resolve:(RCTPromiseResolveBlock)resolve
869
- reject:(RCTPromiseRejectBlock)reject
870
- {
871
- NSString * utf8uri = [uri stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
872
- NSURL * url = [[NSURL alloc] initWithString:utf8uri];
873
- // NSURL * url = [[NSURL alloc] initWithString:uri];
874
- documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
875
- documentController.delegate = self;
876
-
877
- if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
878
- dispatch_sync(dispatch_get_main_queue(), ^{
879
- if([documentController presentPreviewAnimated:YES]) {
880
- resolve(@[[NSNull null]]);
881
- } else {
882
- reject(@"EINVAL", @"document is not supported", nil);
883
- }
884
- });
885
- } else {
886
- reject(@"EINVAL", @"scheme is not supported", nil);
887
- }
888
- }
889
-
890
- # pragma mark - exclude from backup key
891
-
892
- RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
893
- {
894
- [self excludeFromBackupKey:url resolve:resolve reject:reject];
895
- }
896
-
897
- - (void)excludeFromBackupKey:(NSString *)url
898
- resolve:(RCTPromiseResolveBlock)resolve
899
- reject:(RCTPromiseRejectBlock)reject
900
- {
901
- NSError *error = nil;
902
- [ [NSURL URLWithString:url] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
903
- if(!error)
904
- {
905
- resolve(@[[NSNull null]]);
906
- } else {
907
- reject(@"EUNSPECIFIED", [error description], nil);
908
- }
909
-
910
- }
911
-
912
-
913
- RCT_EXPORT_METHOD(df:(RCTResponseSenderBlock)callback)
914
- {
915
- [ReactNativeBlobUtilFS df:callback];
916
- }
917
-
918
- - (UIViewController *)documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
919
- {
920
- UIWindow *window = [UIApplication sharedApplication].keyWindow;
921
- return window.rootViewController;
922
- }
923
-
924
- # pragma mark - Android Only methods
925
- // These methods are required because in the New Arch we have a single spec for both platforms
926
- - (void)actionViewIntent:(NSString *) path
927
- mime:(NSString *) mime
928
- chooserTitle:(NSString *) chooserTitle
929
- resolve:(RCTPromiseResolveBlock)resolve
930
- reject:(RCTPromiseRejectBlock)reject
931
- {
932
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
933
- }
934
-
935
- - (void)addCompleteDownload:(NSDictionary *)config
936
- resolve:(RCTPromiseResolveBlock)resolve
937
- reject:(RCTPromiseRejectBlock)reject
938
- {
939
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
940
- }
941
-
942
- - (void)copyToInternal:(NSString *)contentUri
943
- destpath:(NSString *) destpath
944
- resolve:(RCTPromiseResolveBlock)resolve
945
- reject:(RCTPromiseRejectBlock)reject
946
- {
947
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
948
- }
949
- - (void)copyToMediaStore:(NSDictionary *)filedata
950
- mt:(NSString *) mt
951
- path:(NSString *) path
952
- resolve:(RCTPromiseResolveBlock)resolve
953
- reject:(RCTPromiseRejectBlock)reject
954
- {
955
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
956
- }
957
-
958
- - (void)createMediaFile:(NSDictionary *)filedata
959
- mt:(NSString *) mt
960
- resolve:(RCTPromiseResolveBlock)resolve
961
- reject:(RCTPromiseRejectBlock)reject
962
- {
963
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
964
- }
965
-
966
- - (void)getBlob:(NSString *)contentUri
967
- encoding:(NSString *)encoding
968
- resolve:(RCTPromiseResolveBlock)resolve
969
- reject:(RCTPromiseRejectBlock)reject
970
- {
971
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
972
- }
973
-
974
- - (void)getContentIntent:(NSString *)mime
975
- resolve:(RCTPromiseResolveBlock)resolve
976
- reject:(RCTPromiseRejectBlock)reject
977
- {
978
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
979
- }
980
- - (void)getSDCardDir:(RCTPromiseResolveBlock)resolve
981
- reject:(RCTPromiseRejectBlock)reject
982
- {
983
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
984
- }
985
- - (void)getSDCardApplicationDir:(RCTPromiseResolveBlock)resolve
986
- reject:(RCTPromiseRejectBlock)reject
987
- {
988
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
989
- }
990
- - (void)scanFile:(NSArray *)pairs
991
- callback:(RCTResponseSenderBlock)callback
992
- {
993
- callback(@[@"Scan file method not supported in iOS"]);
994
- }
995
- - (void)writeToMediaFile:(NSString *)fileUri
996
- path:(NSString *)path
997
- transformFile:(BOOL)transformFile
998
- resolve:(RCTPromiseResolveBlock)resolve
999
- reject:(RCTPromiseRejectBlock)reject
1000
- {
1001
- reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
1002
- }
1003
-
1004
- # pragma mark - New Architecture
1005
- #if RCT_NEW_ARCH_ENABLED
1006
- - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
1007
- (const facebook::react::ObjCTurboModule::InitParams &)params
1008
- {
1009
- return std::make_shared<facebook::react::NativeBlobUtilsSpecJSI>(params);
1010
- }
1011
- #endif
1012
-
1013
- @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, PHAsset *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
+ // For PHAsset, get basic metadata
540
+ NSMutableDictionary *assetInfo = [NSMutableDictionary dictionary];
541
+ [assetInfo setValue:[NSNumber numberWithLong:asset.pixelWidth] forKey:@"width"];
542
+ [assetInfo setValue:[NSNumber numberWithLong:asset.pixelHeight] forKey:@"height"];
543
+ [assetInfo setValue:[NSNumber numberWithLong:asset.duration] forKey:@"duration"];
544
+ [assetInfo setValue:[NSDate date] forKey:@"lastModified"];
545
+ [assetInfo setValue:@"asset" forKey:@"type"];
546
+ [assetInfo setValue:@"PHAsset" forKey:@"filename"];
547
+
548
+ // Get actual file size by requesting image data
549
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
550
+ options.synchronous = YES;
551
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
552
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
553
+
554
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
555
+ if (imageData) {
556
+ [assetInfo setValue:[NSNumber numberWithLong:imageData.length] forKey:@"size"];
557
+ } else {
558
+ [assetInfo setValue:[NSNumber numberWithLong:0] forKey:@"size"];
559
+ }
560
+ callback(@[[NSNull null], assetInfo]);
561
+ }];
562
+ }
563
+ else
564
+ {
565
+ callback(@[@"failed to stat path, could not resolve URI", [NSNull null]]);
566
+ }
567
+ }];
568
+ }
569
+
570
+ #pragma mark - fs.lstat
571
+ RCT_EXPORT_METHOD(lstat:(NSString *)path callback:(RCTResponseSenderBlock) callback)
572
+ {
573
+ NSFileManager* fm = [NSFileManager defaultManager];
574
+ BOOL exist = NO;
575
+ BOOL isDir = NO;
576
+
577
+ path = [ReactNativeBlobUtilFS getPathOfAsset:path];
578
+
579
+ exist = [fm fileExistsAtPath:path isDirectory:&isDir];
580
+ if(exist == NO) {
581
+ callback(@[[NSString stringWithFormat:@"failed to lstat path `%@` because it does not exist or it is not a folder", path]]);
582
+ return ;
583
+ }
584
+ NSError * error = nil;
585
+ NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
586
+
587
+ NSMutableArray * res = [[NSMutableArray alloc] init];
588
+ if(isDir == YES) {
589
+ for(NSString * p in files) {
590
+ NSString * filePath = [NSString stringWithFormat:@"%@/%@", path, p];
591
+ [res addObject:[ReactNativeBlobUtilFS stat:filePath error:&error]];
592
+ }
593
+ }
594
+ else {
595
+ [res addObject:[ReactNativeBlobUtilFS stat:path error:&error]];
596
+ }
597
+
598
+ if(error == nil)
599
+ callback(@[[NSNull null], res == nil ? [NSNull null] :res ]);
600
+ else
601
+ callback(@[[error localizedDescription], [NSNull null]]);
602
+
603
+ }
604
+
605
+ #pragma mark - fs.cp
606
+ // Signature for the Old Architecture
607
+ RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
608
+ {
609
+ [self cp:src dest:dest callback:callback];
610
+ }
611
+
612
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
613
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
614
+ - (void)cp:(NSString *)src
615
+ dest:(NSString *)dest
616
+ callback:(RCTResponseSenderBlock)callback
617
+ {
618
+ // path = [ReactNativeBlobUtilFS getPathOfAsset:path];
619
+ [ReactNativeBlobUtilFS getPathFromUri:src completionHandler:^(NSString *path, PHAsset *asset) {
620
+ NSError * error = nil;
621
+ if(path == nil)
622
+ {
623
+ [ReactNativeBlobUtilFS writeAssetToPath:asset dest:dest];
624
+ callback(@[[NSNull null], @YES]);
625
+ }
626
+ else
627
+ {
628
+ // If the destination exists there will be an error
629
+ BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
630
+
631
+ if(error == nil)
632
+ callback(@[[NSNull null], @YES]);
633
+ else
634
+ callback(@[[error localizedDescription], @NO]);
635
+ }
636
+ }];
637
+ }
638
+
639
+ #pragma mark - fs.mv
640
+ // Signature for the Old Architecture
641
+ RCT_EXPORT_METHOD(mv:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback)
642
+ {
643
+ [self mv:path dest:dest callback:callback];
644
+ }
645
+
646
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
647
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
648
+ - (void)mv:(NSString *)path
649
+ dest:(NSString *)dest
650
+ callback:(RCTResponseSenderBlock)callback
651
+ {
652
+ NSError * error = nil;
653
+ BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
654
+
655
+ if(error == nil)
656
+ callback(@[[NSNull null], @YES]);
657
+ else
658
+ callback(@[[error localizedDescription], @NO]);
659
+
660
+ }
661
+
662
+ #pragma mark - fs.mkdir
663
+ RCT_EXPORT_METHOD(mkdir:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
664
+ {
665
+ [self mkdir:path resolve:resolve reject:reject];
666
+ }
667
+
668
+ - (void)mkdir:(NSString *)path
669
+ resolve:(RCTPromiseResolveBlock)resolve
670
+ reject:(RCTPromiseRejectBlock)reject
671
+ {
672
+ [ReactNativeBlobUtilFS mkdir:path resolver:resolve rejecter:reject];
673
+ }
674
+
675
+ #pragma mark - fs.readFile
676
+ // Signature for the Old Architecture
677
+ RCT_EXPORT_METHOD(readFile:(NSString *)path
678
+ encoding:(NSString *)encoding
679
+ transformFile:(BOOL) transformFile
680
+ resolver:(RCTPromiseResolveBlock)resolve
681
+ rejecter:(RCTPromiseRejectBlock)reject)
682
+ {
683
+ [self readFile:path encoding:encoding transformFile:transformFile resolve:resolve reject:reject];
684
+ }
685
+
686
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
687
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
688
+ - (void)readFile:(NSString *)path
689
+ encoding:(NSString *)encoding
690
+ transformFile:(BOOL)transformFile
691
+ resolve:(RCTPromiseResolveBlock)resolve
692
+ reject:(RCTPromiseRejectBlock)reject
693
+ {
694
+
695
+ [ReactNativeBlobUtilFS readFile:path encoding:encoding transformFile:transformFile onComplete:^(NSData * content, NSString * code, NSString * err) {
696
+ if(err != nil) {
697
+ reject(code, err, nil);
698
+ return;
699
+ }
700
+ if([encoding isEqualToString:@"ascii"]) {
701
+ resolve((NSMutableArray *)content);
702
+ } else if([encoding isEqualToString:@"base64"]) {
703
+ resolve([content base64EncodedStringWithOptions:0]);
704
+ } else {
705
+ resolve([[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]);
706
+ }
707
+ }];
708
+ }
709
+
710
+ #pragma mark - fs.hash
711
+ // Signature for the Old Architecture
712
+ RCT_EXPORT_METHOD(hash:(NSString *)path
713
+ algorithm:(NSString *)algorithm
714
+ resolver:(RCTPromiseResolveBlock)resolve
715
+ rejecter:(RCTPromiseRejectBlock)reject)
716
+ {
717
+ [self hash:path algorithm:algorithm resolve:resolve reject:reject];
718
+ }
719
+
720
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
721
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
722
+ - (void)hash:(NSString *)path
723
+ algorithm:(NSString *)algorithm
724
+ resolve:(RCTPromiseResolveBlock)resolve
725
+ reject:(RCTPromiseRejectBlock)reject
726
+ {
727
+ [ReactNativeBlobUtilFS hash:path algorithm:[NSString stringWithString:algorithm] resolver:resolve rejecter:reject];
728
+ }
729
+
730
+ #pragma mark - fs.readStream
731
+ RCT_EXPORT_METHOD(readStream:(NSString *)path encoding:(NSString *)encoding bufferSize:(double)bufferSize tick:(double)tick streamId:(NSString *)streamId)
732
+ {
733
+ if(bufferSize == 0) {
734
+ if([[encoding lowercaseString] isEqualToString:@"base64"])
735
+ bufferSize = 4095;
736
+ else
737
+ bufferSize = 4096;
738
+ }
739
+
740
+ dispatch_async(fsQueue, ^{
741
+ [ReactNativeBlobUtilFS readStream:path encoding:encoding bufferSize:bufferSize tick:tick streamId:streamId baseModule:self];
742
+ });
743
+ }
744
+
745
+ #pragma mark - fs.getEnvironmentDirs
746
+ RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback)
747
+ {
748
+
749
+ callback(@[
750
+ [ReactNativeBlobUtilFS getDocumentDir],
751
+ [ReactNativeBlobUtilFS getCacheDir],
752
+ ]);
753
+ }
754
+
755
+ #pragma mark - net.cancelRequest
756
+ RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBlock)callback) {
757
+ [[ReactNativeBlobUtilNetwork sharedInstance] cancelRequest:taskId];
758
+ callback(@[[NSNull null], taskId]);
759
+
760
+ }
761
+
762
+ #pragma mark - net.enableProgressReport
763
+ RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(double)interval count:(double)count)
764
+ {
765
+ NSNumber *intervalNumber = [NSNumber numberWithDouble:interval];
766
+ NSNumber *countNumber = [NSNumber numberWithInteger:count];
767
+
768
+ ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Download interval:intervalNumber count:countNumber];
769
+ [[ReactNativeBlobUtilNetwork sharedInstance] enableProgressReport:taskId config:cfg];
770
+ }
771
+
772
+ #pragma mark - net.enableUploadProgressReport
773
+ RCT_EXPORT_METHOD(enableUploadProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
774
+ {
775
+ ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Upload interval:interval count:count];
776
+ [[ReactNativeBlobUtilNetwork sharedInstance] enableUploadProgress:taskId config:cfg];
777
+ }
778
+
779
+ #pragma mark - fs.slice
780
+ // Signature for the Old Architecture
781
+ RCT_EXPORT_METHOD(slice:(NSString *)src dest:(NSString *)dest start:(nonnull NSNumber *)start end:(nonnull NSNumber *)end resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
782
+ {
783
+ [self slice:src dest:dest start:start.doubleValue end:end.doubleValue resolve:resolve reject:reject];
784
+ }
785
+
786
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
787
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
788
+ - (void)slice:(NSString *)src
789
+ dest:(NSString *)dest
790
+ start:(double)start
791
+ end:(double)end
792
+ resolve:(RCTPromiseResolveBlock)resolve
793
+ reject:(RCTPromiseRejectBlock)reject
794
+ {
795
+ [ReactNativeBlobUtilFS slice:src dest:dest start:@(start) end:@(end) encode:@"" resolver:resolve rejecter:reject];
796
+ }
797
+
798
+ // Signature for the Old Architecture
799
+ RCT_EXPORT_METHOD(presentOptionsMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
800
+ {
801
+ [self presentOptionsMenu:uri scheme:scheme resolve:resolve reject:reject];
802
+ }
803
+
804
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
805
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
806
+ - (void)presentOptionsMenu:(NSString *)uri
807
+ scheme:(NSString *)scheme
808
+ resolve:(RCTPromiseResolveBlock)resolve
809
+ reject:(RCTPromiseRejectBlock)reject
810
+ {
811
+ NSString * utf8uri = [uri stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
812
+ NSURL * url = [[NSURL alloc] initWithString:utf8uri];
813
+ // NSURL * url = [[NSURL alloc] initWithString:uri];
814
+ documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
815
+ UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
816
+ documentController.delegate = self;
817
+ if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
818
+ CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
819
+ dispatch_sync(dispatch_get_main_queue(), ^{
820
+ [documentController presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES];
821
+ });
822
+ resolve(@[[NSNull null]]);
823
+ } else {
824
+ reject(@"EINVAL", @"scheme is not supported", nil);
825
+ }
826
+ }
827
+
828
+ // Signature for the Old Architecture
829
+ RCT_EXPORT_METHOD(presentOpenInMenu:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
830
+ {
831
+ [self presentOpenInMenu:uri scheme:scheme resolve:resolve reject:reject];
832
+ }
833
+
834
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
835
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
836
+ - (void)presentOpenInMenu:(NSString *)uri
837
+ scheme:(NSString *)scheme
838
+ resolve:(RCTPromiseResolveBlock)resolve
839
+ reject:(RCTPromiseRejectBlock)reject
840
+ {
841
+ NSString * utf8uri = [uri stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
842
+ NSURL * url = [[NSURL alloc] initWithString:utf8uri];
843
+ documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
844
+ UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
845
+ documentController.delegate = self;
846
+ if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
847
+ CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
848
+ dispatch_sync(dispatch_get_main_queue(), ^{
849
+ [documentController presentOpenInMenuFromRect:rect inView:rootCtrl.view animated:YES];
850
+ });
851
+ resolve(@[[NSNull null]]);
852
+ } else {
853
+ reject(@"EINVAL", @"scheme is not supported", nil);
854
+ }
855
+ }
856
+
857
+ # pragma mark - open file with UIDocumentInteractionController and delegate
858
+ // Signature for the Old Architecture
859
+ RCT_EXPORT_METHOD(presentPreview:(NSString*)uri scheme:(NSString *)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
860
+ {
861
+ [self presentPreview:uri scheme:scheme resolve:resolve reject:reject];
862
+ }
863
+
864
+ // Signature for the New Architecture. Codegen can't change the resolve/reject param names and
865
+ // If we change the RCT_EXPORT_METHOD we are going to introduce braking changes we may avoid.
866
+ - (void)presentPreview:(NSString *)uri
867
+ scheme:(NSString *)scheme
868
+ resolve:(RCTPromiseResolveBlock)resolve
869
+ reject:(RCTPromiseRejectBlock)reject
870
+ {
871
+ NSString * utf8uri = [uri stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
872
+ NSURL * url = [[NSURL alloc] initWithString:utf8uri];
873
+ // NSURL * url = [[NSURL alloc] initWithString:uri];
874
+ documentController = [UIDocumentInteractionController interactionControllerWithURL:url];
875
+ documentController.delegate = self;
876
+
877
+ if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) {
878
+ dispatch_sync(dispatch_get_main_queue(), ^{
879
+ if([documentController presentPreviewAnimated:YES]) {
880
+ resolve(@[[NSNull null]]);
881
+ } else {
882
+ reject(@"EINVAL", @"document is not supported", nil);
883
+ }
884
+ });
885
+ } else {
886
+ reject(@"EINVAL", @"scheme is not supported", nil);
887
+ }
888
+ }
889
+
890
+ # pragma mark - exclude from backup key
891
+
892
+ RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
893
+ {
894
+ [self excludeFromBackupKey:url resolve:resolve reject:reject];
895
+ }
896
+
897
+ - (void)excludeFromBackupKey:(NSString *)url
898
+ resolve:(RCTPromiseResolveBlock)resolve
899
+ reject:(RCTPromiseRejectBlock)reject
900
+ {
901
+ NSError *error = nil;
902
+ [ [NSURL URLWithString:url] setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
903
+ if(!error)
904
+ {
905
+ resolve(@[[NSNull null]]);
906
+ } else {
907
+ reject(@"EUNSPECIFIED", [error description], nil);
908
+ }
909
+
910
+ }
911
+
912
+
913
+ RCT_EXPORT_METHOD(df:(RCTResponseSenderBlock)callback)
914
+ {
915
+ [ReactNativeBlobUtilFS df:callback];
916
+ }
917
+
918
+ - (UIViewController *)documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller
919
+ {
920
+ UIWindow *window = [UIApplication sharedApplication].keyWindow;
921
+ return window.rootViewController;
922
+ }
923
+
924
+ # pragma mark - Android Only methods
925
+ // These methods are required because in the New Arch we have a single spec for both platforms
926
+ - (void)actionViewIntent:(NSString *) path
927
+ mime:(NSString *) mime
928
+ chooserTitle:(NSString *) chooserTitle
929
+ resolve:(RCTPromiseResolveBlock)resolve
930
+ reject:(RCTPromiseRejectBlock)reject
931
+ {
932
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
933
+ }
934
+
935
+ - (void)addCompleteDownload:(NSDictionary *)config
936
+ resolve:(RCTPromiseResolveBlock)resolve
937
+ reject:(RCTPromiseRejectBlock)reject
938
+ {
939
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
940
+ }
941
+
942
+ - (void)copyToInternal:(NSString *)contentUri
943
+ destpath:(NSString *) destpath
944
+ resolve:(RCTPromiseResolveBlock)resolve
945
+ reject:(RCTPromiseRejectBlock)reject
946
+ {
947
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
948
+ }
949
+ - (void)copyToMediaStore:(NSDictionary *)filedata
950
+ mt:(NSString *) mt
951
+ path:(NSString *) path
952
+ resolve:(RCTPromiseResolveBlock)resolve
953
+ reject:(RCTPromiseRejectBlock)reject
954
+ {
955
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
956
+ }
957
+
958
+ - (void)createMediaFile:(NSDictionary *)filedata
959
+ mt:(NSString *) mt
960
+ resolve:(RCTPromiseResolveBlock)resolve
961
+ reject:(RCTPromiseRejectBlock)reject
962
+ {
963
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
964
+ }
965
+
966
+ - (void)getBlob:(NSString *)contentUri
967
+ encoding:(NSString *)encoding
968
+ resolve:(RCTPromiseResolveBlock)resolve
969
+ reject:(RCTPromiseRejectBlock)reject
970
+ {
971
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
972
+ }
973
+
974
+ - (void)getContentIntent:(NSString *)mime
975
+ resolve:(RCTPromiseResolveBlock)resolve
976
+ reject:(RCTPromiseRejectBlock)reject
977
+ {
978
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
979
+ }
980
+ - (void)getSDCardDir:(RCTPromiseResolveBlock)resolve
981
+ reject:(RCTPromiseRejectBlock)reject
982
+ {
983
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
984
+ }
985
+ - (void)getSDCardApplicationDir:(RCTPromiseResolveBlock)resolve
986
+ reject:(RCTPromiseRejectBlock)reject
987
+ {
988
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
989
+ }
990
+ - (void)scanFile:(NSArray *)pairs
991
+ callback:(RCTResponseSenderBlock)callback
992
+ {
993
+ callback(@[@"Scan file method not supported in iOS"]);
994
+ }
995
+ - (void)writeToMediaFile:(NSString *)fileUri
996
+ path:(NSString *)path
997
+ transformFile:(BOOL)transformFile
998
+ resolve:(RCTPromiseResolveBlock)resolve
999
+ reject:(RCTPromiseRejectBlock)reject
1000
+ {
1001
+ reject(@"ENOT_SUPPORTED", @"This method is not supported on iOS", nil);
1002
+ }
1003
+
1004
+ # pragma mark - New Architecture
1005
+ #if RCT_NEW_ARCH_ENABLED
1006
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
1007
+ (const facebook::react::ObjCTurboModule::InitParams &)params
1008
+ {
1009
+ return std::make_shared<facebook::react::NativeBlobUtilsSpecJSI>(params);
1010
+ }
1011
+ #endif
1012
+
1013
+ @end