|
@@ -26,6 +26,7 @@ NSString *const FS_EVENT_DATA = @"data";
|
26
|
26
|
NSString *const FS_EVENT_END = @"end";
|
27
|
27
|
NSString *const FS_EVENT_WARN = @"warn";
|
28
|
28
|
NSString *const FS_EVENT_ERROR = @"error";
|
|
29
|
+NSMutableDictionary *fileStreams = nil;
|
29
|
30
|
|
30
|
31
|
////////////////////////////////////////
|
31
|
32
|
//
|
|
@@ -48,12 +49,17 @@ NSString *const FS_EVENT_ERROR = @"error";
|
48
|
49
|
// static member getter
|
49
|
50
|
+ (NSArray *) getFileStreams {
|
50
|
51
|
|
51
|
|
- static NSMutableData *fileStreams = nil;
|
52
|
52
|
if(fileStreams == nil)
|
53
|
|
- fileStreams = [[NSArray alloc] init];
|
|
53
|
+ fileStreams = [[NSMutableDictionary alloc] init];
|
54
|
54
|
return fileStreams;
|
55
|
55
|
}
|
56
|
56
|
|
|
57
|
++(void) setFileStream:(FetchBlobFS *) instance withId:(NSString *) uuid {
|
|
58
|
+ if(fileStreams == nil)
|
|
59
|
+ fileStreams = [[NSMutableDictionary alloc] init];
|
|
60
|
+ [fileStreams setValue:instance forKey:uuid];
|
|
61
|
+}
|
|
62
|
+
|
57
|
63
|
+ (NSString *) getCacheDir {
|
58
|
64
|
return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
|
59
|
65
|
}
|
|
@@ -129,7 +135,7 @@ NSString *const FS_EVENT_ERROR = @"error";
|
129
|
135
|
[self.outStream open];
|
130
|
136
|
NSString *uuid = [[NSUUID UUID] UUIDString];
|
131
|
137
|
self.streamId = uuid;
|
132
|
|
- [[FetchBlobFS getFileStreams] setValue:self forKey:uuid];
|
|
138
|
+ [FetchBlobFS setFileStream:self withId:uuid];
|
133
|
139
|
return uuid;
|
134
|
140
|
}
|
135
|
141
|
|
|
@@ -145,7 +151,7 @@ NSString *const FS_EVENT_ERROR = @"error";
|
145
|
151
|
else if([[self.encoding lowercaseString] isEqualToString:@"ascii"]) {
|
146
|
152
|
decodedData = [chunk dataUsingEncoding:NSASCIIStringEncoding];
|
147
|
153
|
}
|
148
|
|
- NSUInteger left = [chunk length];
|
|
154
|
+ NSUInteger left = [decodedData length];
|
149
|
155
|
NSUInteger nwr = 0;
|
150
|
156
|
do {
|
151
|
157
|
nwr = [self.outStream write:[decodedData bytes] maxLength:left];
|
|
@@ -171,6 +177,15 @@ NSString *const FS_EVENT_ERROR = @"error";
|
171
|
177
|
}
|
172
|
178
|
}
|
173
|
179
|
|
|
180
|
+// close file write stream
|
|
181
|
+- (void)closeOutStream {
|
|
182
|
+ if(self.outStream != nil) {
|
|
183
|
+ [self.outStream close];
|
|
184
|
+ self.outStream = nil;
|
|
185
|
+ }
|
|
186
|
+
|
|
187
|
+}
|
|
188
|
+
|
174
|
189
|
- (void)readWithPath:(NSString *)path useEncoding:(NSString *)encoding bufferSize:(int) bufferSize{
|
175
|
190
|
|
176
|
191
|
self.inStream = [[NSInputStream alloc] initWithFileAtPath:path];
|
|
@@ -184,22 +199,13 @@ NSString *const FS_EVENT_ERROR = @"error";
|
184
|
199
|
// start NSStream is a runloop
|
185
|
200
|
dispatch_async(queue, ^ {
|
186
|
201
|
[inStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
|
187
|
|
- forMode:NSDefaultRunLoopMode];
|
|
202
|
+ forMode:NSDefaultRunLoopMode];
|
188
|
203
|
[inStream open];
|
189
|
204
|
[[NSRunLoop currentRunLoop] run];
|
190
|
|
-
|
|
205
|
+
|
191
|
206
|
});
|
192
|
207
|
}
|
193
|
208
|
|
194
|
|
-// close file write stream
|
195
|
|
-- (void)closeOutStream {
|
196
|
|
- if(self.outStream != nil) {
|
197
|
|
- [self.outStream close];
|
198
|
|
- self.outStream = nil;
|
199
|
|
- }
|
200
|
|
-
|
201
|
|
-}
|
202
|
|
-
|
203
|
209
|
// close file read stream
|
204
|
210
|
- (void)closeInStream {
|
205
|
211
|
if(self.inStream != nil) {
|
|
@@ -245,7 +251,7 @@ void runOnMainQueueWithoutDeadlocking(void (^block)(void))
|
245
|
251
|
NSMutableData * chunkData = [[NSMutableData data] init];
|
246
|
252
|
NSInteger chunkSize = 4096;
|
247
|
253
|
if([[self.encoding lowercaseString] isEqualToString:@"base64"])
|
248
|
|
- chunkSize = 4098;
|
|
254
|
+ chunkSize = 4095;
|
249
|
255
|
if(self.bufferSize > 0)
|
250
|
256
|
chunkSize = self.bufferSize;
|
251
|
257
|
uint8_t buf[chunkSize];
|
|
@@ -257,7 +263,7 @@ void runOnMainQueueWithoutDeadlocking(void (^block)(void))
|
257
|
263
|
[chunkData appendBytes:(const void *)buf length:len];
|
258
|
264
|
// TODO : file read progress ?
|
259
|
265
|
// dispatch data event
|
260
|
|
- NSString * encodedChunk;
|
|
266
|
+ NSString * encodedChunk = [NSString alloc];
|
261
|
267
|
if( [[self.encoding lowercaseString] isEqualToString:@"utf8"] ) {
|
262
|
268
|
encodedChunk = [encodedChunk initWithData:chunkData encoding:NSUTF8StringEncoding];
|
263
|
269
|
}
|
|
@@ -277,15 +283,15 @@ void runOnMainQueueWithoutDeadlocking(void (^block)(void))
|
277
|
283
|
];
|
278
|
284
|
return;
|
279
|
285
|
}
|
280
|
|
- runOnMainQueueWithoutDeadlocking(^{
|
281
|
|
- [self.bridge.eventDispatcher
|
282
|
|
- sendDeviceEventWithName:streamEventCode
|
283
|
|
- body:@{
|
284
|
|
- @"event": FS_EVENT_DATA,
|
285
|
|
- @"detail": encodedChunk
|
286
|
|
- }
|
287
|
|
- ];
|
288
|
|
- });
|
|
286
|
+
|
|
287
|
+ [self.bridge.eventDispatcher
|
|
288
|
+ sendDeviceEventWithName:streamEventCode
|
|
289
|
+ body:@{
|
|
290
|
+ @"event": FS_EVENT_DATA,
|
|
291
|
+ @"detail": encodedChunk
|
|
292
|
+ }
|
|
293
|
+ ];
|
|
294
|
+
|
289
|
295
|
}
|
290
|
296
|
// end of stream
|
291
|
297
|
else {
|
|
@@ -647,6 +653,30 @@ RCT_EXPORT_METHOD(fetchBlob:(NSDictionary *)options
|
647
|
653
|
});
|
648
|
654
|
}
|
649
|
655
|
|
|
656
|
+RCT_EXPORT_METHOD(createFile:(NSString *)path data:(NSString *)data encoding:(NSString *)encoding callback:(RCTResponseSenderBlock)callback) {
|
|
657
|
+
|
|
658
|
+ NSFileManager * fm = [NSFileManager defaultManager];
|
|
659
|
+ NSData * fileContent = nil;
|
|
660
|
+
|
|
661
|
+ if([[encoding lowercaseString] isEqualToString:@"utf8"]) {
|
|
662
|
+ fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]];
|
|
663
|
+ }
|
|
664
|
+ else if([[encoding lowercaseString] isEqualToString:@"base64"]) {
|
|
665
|
+ fileContent = [[NSData alloc] initWithBase64EncodedData:data options:0];
|
|
666
|
+ }
|
|
667
|
+ else {
|
|
668
|
+ fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
|
|
669
|
+ }
|
|
670
|
+
|
|
671
|
+ BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
|
|
672
|
+ if(success == YES)
|
|
673
|
+ callback(@[[NSNull null]]);
|
|
674
|
+ else
|
|
675
|
+ callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]);
|
|
676
|
+
|
|
677
|
+}
|
|
678
|
+
|
|
679
|
+
|
650
|
680
|
RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callback) {
|
651
|
681
|
BOOL isDir = NO;
|
652
|
682
|
BOOL exists = NO;
|
|
@@ -657,6 +687,12 @@ RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callb
|
657
|
687
|
|
658
|
688
|
RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize) {
|
659
|
689
|
FetchBlobFS *fileStream = [[FetchBlobFS alloc] initWithBridgeRef:self.bridge];
|
|
690
|
+ if(bufferSize == nil) {
|
|
691
|
+ if([[encoding lowercaseString] isEqualToString:@"base64"])
|
|
692
|
+ bufferSize = 4095;
|
|
693
|
+ else
|
|
694
|
+ bufferSize = 4096;
|
|
695
|
+ }
|
660
|
696
|
[fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
|
661
|
697
|
}
|
662
|
698
|
|
|
@@ -664,7 +700,7 @@ RCT_EXPORT_METHOD(writeStream:(NSString *)path withEncoding:(NSString *)encoding
|
664
|
700
|
FetchBlobFS * fileStream = [[FetchBlobFS alloc] initWithBridgeRef:self.bridge];
|
665
|
701
|
NSFileManager * fm = [NSFileManager defaultManager];
|
666
|
702
|
BOOL isDir = nil;
|
667
|
|
- BOOL exist = ![fm fileExistsAtPath:path isDirectory:&isDir];
|
|
703
|
+ BOOL exist = [fm fileExistsAtPath:path isDirectory:&isDir];
|
668
|
704
|
if( exist == NO || isDir == YES) {
|
669
|
705
|
callback(@[[NSString stringWithFormat:@"target path `%@` may not exists or it's a folder", path]]);
|
670
|
706
|
return;
|
|
@@ -711,6 +747,14 @@ RCT_EXPORT_METHOD(removeSession:(NSArray *)paths callback:(RCTResponseSenderBloc
|
711
|
747
|
}
|
712
|
748
|
|
713
|
749
|
RCT_EXPORT_METHOD(ls:(NSString *)path callback:(RCTResponseSenderBlock) callback) {
|
|
750
|
+ NSFileManager* fm = [NSFileManager defaultManager];
|
|
751
|
+ BOOL exist = nil;
|
|
752
|
+ BOOL isDir = nil;
|
|
753
|
+ exist = [fm fileExistsAtPath:path isDirectory:&isDir];
|
|
754
|
+ if(exist == NO || isDir == NO) {
|
|
755
|
+ callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not a folder", path]]);
|
|
756
|
+ return ;
|
|
757
|
+ }
|
714
|
758
|
NSError * error = nil;
|
715
|
759
|
NSArray * result = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
|
716
|
760
|
|
|
@@ -723,7 +767,7 @@ RCT_EXPORT_METHOD(ls:(NSString *)path callback:(RCTResponseSenderBlock) callback
|
723
|
767
|
|
724
|
768
|
RCT_EXPORT_METHOD(cp:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback) {
|
725
|
769
|
NSError * error = nil;
|
726
|
|
- BOOL result = [[NSFileManager defaultManager] copyItemAtURL:path toURL:dest error:&error];
|
|
770
|
+ BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
|
727
|
771
|
|
728
|
772
|
if(error == nil)
|
729
|
773
|
callback(@[[NSNull null], @YES]);
|
|
@@ -734,7 +778,7 @@ RCT_EXPORT_METHOD(cp:(NSString *)path toPath:(NSString *)dest callback:(RCTRespo
|
734
|
778
|
|
735
|
779
|
RCT_EXPORT_METHOD(mv:(NSString *)path toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback) {
|
736
|
780
|
NSError * error = nil;
|
737
|
|
- BOOL result = [[NSFileManager defaultManager] moveItemAtURL:path toURL:dest error:&error];
|
|
781
|
+ BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error];
|
738
|
782
|
|
739
|
783
|
if(error == nil)
|
740
|
784
|
callback(@[[NSNull null], @YES]);
|
|
@@ -744,8 +788,10 @@ RCT_EXPORT_METHOD(mv:(NSString *)path toPath:(NSString *)dest callback:(RCTRespo
|
744
|
788
|
}
|
745
|
789
|
|
746
|
790
|
RCT_EXPORT_METHOD(mkdir:(NSString *)path callback:(RCTResponseSenderBlock) callback) {
|
747
|
|
- if([FetchBlobFS exists:path])
|
748
|
|
- callback(@[@"file path exists"]);
|
|
791
|
+ if([FetchBlobFS exists:path]) {
|
|
792
|
+ callback(@[@"mkdir failed, folder already exists"]);
|
|
793
|
+ return;
|
|
794
|
+ }
|
749
|
795
|
else
|
750
|
796
|
[FetchBlobFS mkdir:path];
|
751
|
797
|
callback(@[[NSNull null]]);
|