瀏覽代碼

Improve file API consistency #18

Ben Hsieh 9 年之前
父節點
當前提交
c5212450e3
共有 4 個文件被更改,包括 110 次插入40 次删除
  1. 52
    18
      src/fs.js
  2. 2
    1
      src/index.js
  3. 3
    0
      src/ios/RNFetchBlob/RNFetchBlob.h
  4. 53
    21
      src/ios/RNFetchBlob/RNFetchBlob.m

+ 52
- 18
src/fs.js 查看文件

24
 
24
 
25
 /**
25
 /**
26
  * Get path of system directories.
26
  * Get path of system directories.
27
- * @return {object} Map contains PictureDir, MovieDir, DocumentDir, CacheDir,
28
- * MusicDir, and DCIMDir, some directory might not be supported by platform.
27
+ * @return {object} Map contains DocumentDir, CacheDir, DCIMDir, DownloadDir,
28
+ * , some directory might not be supported by platform.
29
  */
29
  */
30
 function getSystemDirs() {
30
 function getSystemDirs() {
31
   return new Promise((resolve, reject) => {
31
   return new Promise((resolve, reject) => {
32
     try {
32
     try {
33
       RNFetchBlob.getEnvironmentDirs((...dirs) => {
33
       RNFetchBlob.getEnvironmentDirs((...dirs) => {
34
-        let [PictureDir, MovieDir, DocumentDir, CacheDir, MusicDir, DCIMDir] = [...dirs]
35
-        resolve({PictureDir, MovieDir, DocumentDir, CacheDir, MusicDir, DCIMDir})
34
+        let [DocumentDir, CacheDir, DCIMDir, DownloadDir] = [...dirs]
35
+        resolve({DocumentDir, CacheDir, DCIMDir, DownloadDir})
36
       })
36
       })
37
     } catch(err) {
37
     } catch(err) {
38
       reject(err)
38
       reject(err)
55
   }
55
   }
56
 }
56
 }
57
 
57
 
58
+/**
59
+ * Create write stream to a file.
60
+ * @param  {string} path Target path of file stream.
61
+ * @param  {string} encoding Encoding of input data.
62
+ * @param  {bool} append  A flag represent if data append to existing ones.
63
+ * @return {Promise<WriteStream>} A promise resolves a `WriteStream` object.
64
+ */
58
 function writeStream(
65
 function writeStream(
59
-  path:string,
60
-  encoding:'utf8' | 'ascii' | 'base64',
61
-  callback:(streamId:string) => void
66
+  path : string,
67
+  encoding : 'utf8' | 'ascii' | 'base64',
68
+  append? : ?bool,
62
 ):Promise<WriteStream> {
69
 ):Promise<WriteStream> {
63
   if(!path)
70
   if(!path)
64
     throw Error('RNFetchBlob could not open file stream with empty `path`')
71
     throw Error('RNFetchBlob could not open file stream with empty `path`')
65
   encoding = encoding || 'base64'
72
   encoding = encoding || 'base64'
66
   return new Promise((resolve, reject) => {
73
   return new Promise((resolve, reject) => {
67
-    RNFetchBlob.writeStream(path, encoding || 'base64', (streamId:string) => {
68
-      resolve(new WriteStream(streamId))
74
+    RNFetchBlob.writeStream(path, encoding || 'base64', append || false, (err, streamId:string) => {
75
+      if(err)
76
+        reject(err)
77
+      else
78
+        resolve(new WriteStream(streamId))
69
     })
79
     })
70
   })
80
   })
71
 }
81
 }
72
 
82
 
73
 /**
83
 /**
74
  * Create file stream from file at `path`.
84
  * Create file stream from file at `path`.
75
- * @param  {String} path   The file path.
76
- * @param  {String} encoding Data encoding, should be one of `base64`, `utf8`, `ascii`
77
- * @param  {String} bufferSize Size of stream buffer.
85
+ * @param  {string} path   The file path.
86
+ * @param  {string} encoding Data encoding, should be one of `base64`, `utf8`, `ascii`
87
+ * @param  {boolean} bufferSize Size of stream buffer.
78
  * @return {RNFetchBlobStream} RNFetchBlobStream stream instance.
88
  * @return {RNFetchBlobStream} RNFetchBlobStream stream instance.
79
  */
89
  */
80
 function readStream(
90
 function readStream(
81
-  path:string,
82
-  encoding:'utf8' | 'ascii' | 'base64',
83
-  bufferSize?:?number
91
+  path : string,
92
+  encoding : 'utf8' | 'ascii' | 'base64',
93
+  bufferSize? : ?number
84
 ):RNFetchBlobStream {
94
 ):RNFetchBlobStream {
85
 
95
 
86
   if(!path)
96
   if(!path)
183
   })
193
   })
184
 }
194
 }
185
 
195
 
196
+/**
197
+ * Check if file exists and if it is a folder.
198
+ * @param  {string} path Path to check
199
+ * @return {Promise<bool, bool>}
200
+ */
201
+function exists(path:string):Promise<bool, bool> {
202
+
203
+  return new Promise((resolve, reject) => {
204
+    try {
205
+      RNFetchBlob.exists(path, (exist, isDir) => {
206
+        resolve(exist, isDir)
207
+      })
208
+    } catch(err) {
209
+      reject(err)
210
+    }
211
+  })
212
+
213
+}
214
+
186
 /**
215
 /**
187
  * Session class
216
  * Session class
188
  * @class RNFetchBlobSession
217
  * @class RNFetchBlobSession
244
 
273
 
245
   id : string;
274
   id : string;
246
   encoding : string;
275
   encoding : string;
276
+  append : bool;
247
 
277
 
248
-  constructor(streamId:string, encoding:string) {
278
+  constructor(streamId:string, encoding:string, append:string) {
249
     this.id = streamId
279
     this.id = streamId
250
     this.encoding = encoding
280
     this.encoding = encoding
281
+    this.append = append
251
   }
282
   }
252
 
283
 
253
   write() {
284
   write() {
254
     return new Promise((resolve, reject) => {
285
     return new Promise((resolve, reject) => {
255
       try {
286
       try {
256
-        RNFetchBlob.writeChunk(this.id, data, this.encoding, () => {
257
-          resolve()
287
+        RNFetchBlob.writeChunk(this.id, data, (error) => {
288
+          if(error)
289
+            reject(error)
290
+          else
291
+            resolve()
258
         })
292
         })
259
       } catch(err) {
293
       } catch(err) {
260
         reject(err)
294
         reject(err)

+ 2
- 1
src/index.js 查看文件

26
   unlink,
26
   unlink,
27
   mkdir,
27
   mkdir,
28
   session,
28
   session,
29
+  writeStream,
29
   ls,
30
   ls,
30
   mv,
31
   mv,
31
   cp
32
   cp
244
 }
245
 }
245
 
246
 
246
 export default {
247
 export default {
247
-  fetch, base64, config, getSystemDirs, readStream, unlink, session, ls, mkdir, mv, cp
248
+  fetch, base64, config, getSystemDirs, readStream, unlink, session, ls, mkdir, mv, cp, writeStream
248
 }
249
 }

+ 3
- 0
src/ios/RNFetchBlob/RNFetchBlob.h 查看文件

35
     Boolean isOpen;
35
     Boolean isOpen;
36
     NSString * encoding;
36
     NSString * encoding;
37
     int bufferSize;
37
     int bufferSize;
38
+    BOOL appendData;
38
     NSString * taskId;
39
     NSString * taskId;
39
     NSString * path;
40
     NSString * path;
40
     NSString * streamId;
41
     NSString * streamId;
49
 @property (nonatomic) NSString * path;
50
 @property (nonatomic) NSString * path;
50
 @property (nonatomic) int bufferSize;
51
 @property (nonatomic) int bufferSize;
51
 @property (nonatomic) NSString * streamId;
52
 @property (nonatomic) NSString * streamId;
53
+@property (nonatomic) BOOL appendData;
52
 
54
 
53
 + (NSString *) getTempPath;
55
 + (NSString *) getTempPath;
54
 + (FetchBlobFS *) getFileStreams;
56
 + (FetchBlobFS *) getFileStreams;
85
 @property (nonatomic) NSDictionary * options;
87
 @property (nonatomic) NSDictionary * options;
86
 @property (nonatomic) FetchBlobFS * fileStream;
88
 @property (nonatomic) FetchBlobFS * fileStream;
87
 
89
 
90
+
88
 - (id) init;
91
 - (id) init;
89
 - (void) sendRequest;
92
 - (void) sendRequest;
90
 
93
 

+ 53
- 21
src/ios/RNFetchBlob/RNFetchBlob.m 查看文件

42
 @synthesize callback;
42
 @synthesize callback;
43
 @synthesize taskId;
43
 @synthesize taskId;
44
 @synthesize path;
44
 @synthesize path;
45
+@synthesize appendData;
45
 @synthesize bufferSize;
46
 @synthesize bufferSize;
46
 
47
 
47
 // static member getter
48
 // static member getter
120
     return self;
121
     return self;
121
 }
122
 }
122
 
123
 
123
-- (NSString *)openWithPath:(NSString *)destPath {
124
-    self.outStream = [[NSOutputStream alloc] initToFileAtPath:destPath append:YES];
124
+// Create file stream for write data
125
+- (NSString *)openWithPath:(NSString *)destPath encode:(nullable NSString *)encode appendData:(BOOL)append {
126
+    self.outStream = [[NSOutputStream alloc] initToFileAtPath:destPath append:append];
127
+    self.encoding = encode;
125
     [self.outStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
128
     [self.outStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
126
     [self.outStream open];
129
     [self.outStream open];
127
     NSString *uuid = [[NSUUID UUID] UUIDString];
130
     NSString *uuid = [[NSUUID UUID] UUIDString];
130
     return uuid;
133
     return uuid;
131
 }
134
 }
132
 
135
 
136
+// Write file chunk into an opened stream
137
+- (void)writeEncodeChunk:(NSString *) chunk {
138
+    NSMutableData * decodedData = [NSData alloc];
139
+    if([[self.encoding lowercaseString] isEqualToString:@"base64"]) {
140
+        decodedData = [chunk dataUsingEncoding:NSUTF8StringEncoding];
141
+    }
142
+    if([[self.encoding lowercaseString] isEqualToString:@"utf8"]) {
143
+        decodedData = [chunk dataUsingEncoding:NSUTF8StringEncoding];
144
+    }
145
+    else if([[self.encoding lowercaseString] isEqualToString:@"ascii"]) {
146
+        decodedData = [chunk dataUsingEncoding:NSASCIIStringEncoding];
147
+    }
148
+    NSUInteger left = [chunk length];
149
+    NSUInteger nwr = 0;
150
+    do {
151
+        nwr = [self.outStream write:[decodedData bytes] maxLength:left];
152
+        if (-1 == nwr) break;
153
+        left -= nwr;
154
+    } while (left > 0);
155
+    if (left) {
156
+        NSLog(@"stream error: %@", [self.outStream streamError]);
157
+    }
158
+}
159
+
133
 // Write file chunk into an opened stream
160
 // Write file chunk into an opened stream
134
 - (void)write:(NSData *) chunk {
161
 - (void)write:(NSData *) chunk {
135
     NSUInteger left = [chunk length];
162
     NSUInteger left = [chunk length];
342
     // open file stream for write
369
     // open file stream for write
343
     if( path != nil) {
370
     if( path != nil) {
344
         self.fileStream = [[FetchBlobFS alloc]initWithCallback:self.callback];
371
         self.fileStream = [[FetchBlobFS alloc]initWithCallback:self.callback];
345
-        [self.fileStream openWithPath:path];
372
+        [self.fileStream openWithPath:path encode:@"ascii" appendData:YES ];
346
     }
373
     }
347
     else if ( [self.options valueForKey:CONFIG_USE_TEMP]!= nil ) {
374
     else if ( [self.options valueForKey:CONFIG_USE_TEMP]!= nil ) {
348
         self.fileStream = [[FetchBlobFS alloc]initWithCallback:self.callback];
375
         self.fileStream = [[FetchBlobFS alloc]initWithCallback:self.callback];
349
-        [self.fileStream openWithPath:[FetchBlobFS getTempPath:taskId withExtension:ext]];
376
+        [self.fileStream openWithPath:[FetchBlobFS getTempPath:taskId withExtension:ext] encode:@"ascii" appendData:YES];
350
     }
377
     }
351
     
378
     
352
     NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO];
379
     NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO];
620
     });
647
     });
621
 }
648
 }
622
 
649
 
650
+RCT_EXPORT_METHOD(exists:(NSString *)path callback:(RCTResponseSenderBlock)callback) {
651
+    BOOL isDir = NO;
652
+    BOOL exists = NO;
653
+    exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory: &isDir];
654
+    callback(@[@(exists), @(isDir)]);
655
+
656
+}
657
+
623
 RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize) {
658
 RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize) {
624
     FetchBlobFS *fileStream = [[FetchBlobFS alloc] initWithBridgeRef:self.bridge];
659
     FetchBlobFS *fileStream = [[FetchBlobFS alloc] initWithBridgeRef:self.bridge];
625
     [fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
660
     [fileStream readWithPath:path useEncoding:encoding bufferSize:bufferSize];
626
 }
661
 }
627
 
662
 
628
-RCT_EXPORT_METHOD(writeStream:(NSString *)path withEncoding:(NSString *)encoding callback:(RCTResponseSenderBlock)callback) {
629
-    FetchBlobFS *fileStream = [[FetchBlobFS alloc] initWithBridgeRef:self.bridge];
630
-    NSString * streamId = [fileStream openWithPath:path];
631
-    callback(@[streamId]);
663
+RCT_EXPORT_METHOD(writeStream:(NSString *)path withEncoding:(NSString *)encoding appendData:(BOOL)append callback:(RCTResponseSenderBlock)callback) {
664
+    FetchBlobFS * fileStream = [[FetchBlobFS alloc] initWithBridgeRef:self.bridge];
665
+    NSFileManager * fm = [NSFileManager defaultManager];
666
+    BOOL isDir = nil;
667
+    BOOL exist = ![fm fileExistsAtPath:path isDirectory:&isDir];
668
+    if( exist == NO || isDir == YES) {
669
+        callback(@[[NSString stringWithFormat:@"target path `%@` may not exists or it's a folder", path]]);
670
+        return;
671
+    }
672
+    NSString * streamId = [fileStream openWithPath:path encode:encoding appendData:append];
673
+    callback(@[[NSNull null], streamId]);
632
 }
674
 }
633
 
675
 
634
-RCT_EXPORT_METHOD(writeChunk:(NSString *)streamId withData:(NSString *)data encoding:(NSString *)encode callback:(RCTResponseSenderBlock) callback) {
676
+RCT_EXPORT_METHOD(writeChunk:(NSString *)streamId withData:(NSString *)data callback:(RCTResponseSenderBlock) callback) {
635
     FetchBlobFS *fs = [[FetchBlobFS getFileStreams] valueForKey:streamId];
677
     FetchBlobFS *fs = [[FetchBlobFS getFileStreams] valueForKey:streamId];
636
-    NSMutableData * decodedData = [NSData alloc];
637
-    if([[encode lowercaseString] isEqualToString:@"base64"]) {
638
-        [fs write:[data dataUsingEncoding:NSUTF8StringEncoding]];
639
-    }
640
-    if([[encode lowercaseString] isEqualToString:@"utf8"]) {
641
-        [fs write:[data dataUsingEncoding:NSUTF8StringEncoding]];
642
-    }
643
-    else if([[encode lowercaseString] isEqualToString:@"ascii"]) {
644
-        [fs write:[data dataUsingEncoding:NSASCIIStringEncoding]];
645
-    }
678
+    [fs writeEncodeChunk:data];
679
+    callback(@[[NSNull null]]);
646
 }
680
 }
647
 
681
 
648
 RCT_EXPORT_METHOD(closeStream:(NSString *)streamId callback:(RCTResponseSenderBlock) callback) {
682
 RCT_EXPORT_METHOD(closeStream:(NSString *)streamId callback:(RCTResponseSenderBlock) callback) {
720
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {
754
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {
721
     
755
     
722
     callback(@[
756
     callback(@[
723
-               [FetchBlobFS getPictureDir],
724
-               [FetchBlobFS getMovieDir],
725
                [FetchBlobFS getDocumentDir],
757
                [FetchBlobFS getDocumentDir],
726
                [FetchBlobFS getCacheDir],
758
                [FetchBlobFS getCacheDir],
727
             ]);
759
             ]);