Browse Source

#27 add append option to writeFile API

Ben Hsieh 8 years ago
parent
commit
2a80b5b092

+ 4
- 4
src/android/src/main/java/com/RNFetchBlob/RNFetchBlob.java View File

@@ -99,13 +99,13 @@ public class RNFetchBlob extends ReactContextBaseJavaModule {
99 99
     }
100 100
 
101 101
     @ReactMethod
102
-    public void writeFileArray(String path, ReadableArray data, Promise promise) {
103
-        RNFetchBlobFS.writeFile(path, data, promise);
102
+    public void writeFileArray(String path, ReadableArray data, boolean append, Promise promise) {
103
+        RNFetchBlobFS.writeFile(path, data, append, promise);
104 104
     }
105 105
 
106 106
     @ReactMethod
107
-    public void writeFile(String path, String encoding, String data, Promise promise) {
108
-        RNFetchBlobFS.writeFile(path, encoding, data, promise);
107
+    public void writeFile(String path, String encoding, String data, boolean append, Promise promise) {
108
+        RNFetchBlobFS.writeFile(path, encoding, data, append, promise);
109 109
     }
110 110
 
111 111
     @ReactMethod

+ 4
- 4
src/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java View File

@@ -59,7 +59,7 @@ public class RNFetchBlobFS {
59 59
      * @param data Array passed from JS context.
60 60
      * @param promise
61 61
      */
62
-    static public void writeFile(String path, String encoding, String data, final Promise promise) {
62
+    static public void writeFile(String path, String encoding, String data, final boolean append, final Promise promise) {
63 63
         AsyncTask<String, Integer, Integer> task = new AsyncTask<String, Integer, Integer>() {
64 64
             @Override
65 65
             protected Integer doInBackground(String... args) {
@@ -71,7 +71,7 @@ public class RNFetchBlobFS {
71 71
                     File dir = f.getParentFile();
72 72
                     if(!dir.exists())
73 73
                         dir.mkdirs();
74
-                    FileOutputStream fout = new FileOutputStream(f);
74
+                    FileOutputStream fout = new FileOutputStream(f, append);
75 75
                     fout.write(stringToBytes(data, encoding));
76 76
                     fout.close();
77 77
                     promise.resolve(Arguments.createArray());
@@ -90,7 +90,7 @@ public class RNFetchBlobFS {
90 90
      * @param data Array passed from JS context.
91 91
      * @param promise
92 92
      */
93
-    static public void writeFile(String path, ReadableArray data, final Promise promise) {
93
+    static public void writeFile(String path, ReadableArray data, final boolean append, final Promise promise) {
94 94
         AsyncTask<Object, Void, Void> task = new AsyncTask<Object, Void, Void>() {
95 95
             @Override
96 96
             protected Void doInBackground(Object... args) {
@@ -101,7 +101,7 @@ public class RNFetchBlobFS {
101 101
                     File dir = f.getParentFile();
102 102
                     if(!dir.exists())
103 103
                         dir.mkdirs();
104
-                    FileOutputStream os = new FileOutputStream(f);
104
+                    FileOutputStream os = new FileOutputStream(f, append);
105 105
                     byte [] bytes = new byte[data.size()];
106 106
                     for(int i=0;i<data.size();i++) {
107 107
                         bytes[i] = (byte) data.getInt(i);

+ 28
- 3
src/fs.js View File

@@ -139,19 +139,44 @@ function readFile(path:string, encoding:string, bufferSize:number):Promise<any>
139 139
   return RNFetchBlob.readFile(path, encoding)
140 140
 }
141 141
 
142
-function writeFile(path:string, encoding:string, data:string | Array<number>):Promise {
142
+/**
143
+ * Write data to file.
144
+ * @param  {string} path  Path of the file.
145
+ * @param  {string | number[]} data Data to write to the file.
146
+ * @param  {string} encoding Encoding of data (Optional).
147
+ * @return {Promise}
148
+ */
149
+function writeFile(path:string, data:string | Array<number>, encoding:?string):Promise {
150
+  encoding = encoding || 'utf8'
151
+  if(typeof path !== 'string')
152
+    return Promise.reject('Invalid argument "path" ')
153
+  if(encoding.toLocaleLowerCase() === 'ascii') {
154
+    if(!Array.isArray(data))
155
+      Promise.reject(`Expected "data" is an Array when encoding is "ascii", however got ${typeof data}`)
156
+    else
157
+      return RNFetchBlob.writeFileArray(path, data, false);
158
+  } else {
159
+    if(typeof data !== 'string')
160
+      Promise.reject(`Expected "data" is a String when encoding is "utf8" or "base64", however got ${typeof data}`)
161
+    else
162
+      return RNFetchBlob.writeFile(path, encoding, data, false);
163
+  }
164
+}
165
+
166
+function appendFile(path:string, data:string | Array<number>, encoding:?string):Promise {
167
+  encoding = encoding || 'utf8'
143 168
   if(typeof path !== 'string')
144 169
     return Promise.reject('Invalid argument "path" ')
145 170
   if(encoding.toLocaleLowerCase() === 'ascii') {
146 171
     if(!Array.isArray(data))
147 172
       Promise.reject(`Expected "data" is an Array when encoding is "ascii", however got ${typeof data}`)
148 173
     else
149
-      return RNFetchBlob.writeFileArray(path, data);
174
+      return RNFetchBlob.writeFileArray(path, data, true);
150 175
   } else {
151 176
     if(typeof data !== 'string')
152 177
       Promise.reject(`Expected "data" is a String when encoding is "utf8" or "base64", however got ${typeof data}`)
153 178
     else
154
-      return RNFetchBlob.writeFile(path, encoding, data);
179
+      return RNFetchBlob.writeFile(path, encoding, data, true);
155 180
   }
156 181
 }
157 182
 

+ 4
- 4
src/ios/RNFetchBlob/RNFetchBlob.m View File

@@ -415,12 +415,12 @@ RCT_EXPORT_METHOD(readFile:(NSString *)path encoding:(NSString *)encoding resolv
415 415
     [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject];
416 416
 })
417 417
 
418
-RCT_EXPORT_METHOD(writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
419
-    [RNFetchBlobFS writeFile:path encoding:encoding data:data resolver:resolve rejecter:reject];
418
+RCT_EXPORT_METHOD(writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
419
+    [RNFetchBlobFS writeFile:path encoding:encoding data:data append:append resolver:resolve rejecter:reject];
420 420
 })
421 421
 
422
-RCT_EXPORT_METHOD(writeFileArray:(NSString *)path data:(NSArray *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
423
-    [RNFetchBlobFS writeFileArray:path data:data resolver:resolve rejecter:reject];
422
+RCT_EXPORT_METHOD(writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
423
+    [RNFetchBlobFS writeFileArray:path data:data append:append resolver:resolve rejecter:reject];
424 424
 })
425 425
 
426 426
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {

+ 2
- 2
src/ios/RNFetchBlobFS.h View File

@@ -48,8 +48,8 @@
48 48
 + (BOOL) mkdir:(NSString *) path;
49 49
 + (NSDictionary *) stat:(NSString *) path error:(NSError **) error;
50 50
 + (BOOL) exists:(NSString *) path;
51
-+ (void) writeFileArray:(NSString *)path data:(NSArray *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
52
-+ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
51
++ (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
52
++ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
53 53
 + (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
54 54
 
55 55
 // constructor

+ 40
- 14
src/ios/RNFetchBlobFS.m View File

@@ -84,14 +84,17 @@ NSMutableDictionary *fileStreams = nil;
84 84
     return tempPath;
85 85
 }
86 86
 
87
-+ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
87
++ (void) writeFile:(NSString *)path encoding:(NSString *)encoding data:(NSString *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
88 88
     @try {
89 89
         NSFileManager * fm = [NSFileManager defaultManager];
90 90
         NSError * err = nil;
91
+        // check if the folder exists, if not exists, create folders recursively
92
+        // after the folders created, write data into the file
91 93
         NSString * folder = [path stringByDeletingLastPathComponent];
92 94
         if(![fm fileExistsAtPath:folder]) {
93 95
             [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
94 96
         }
97
+        // if file exists, write file by encoding and strategy
95 98
         if(![fm fileExistsAtPath:path]) {
96 99
             if([[encoding lowercaseString] isEqualToString:@"base64"]){
97 100
                 NSData * byteData = [[NSData alloc] initWithBase64EncodedString:data options:0];
@@ -102,14 +105,21 @@ NSMutableDictionary *fileStreams = nil;
102 105
         }
103 106
         else {
104 107
             NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
105
-            [fileHandle seekToEndOfFile];
108
+            NSData * content = nil;
106 109
             if([[encoding lowercaseString] isEqualToString:@"base64"]) {
107
-                NSData * byteData = [[NSData alloc] initWithBase64EncodedString:data options:0];
108
-                [fileHandle writeData:byteData];
110
+                content = [[NSData alloc] initWithBase64EncodedString:data options:0];
111
+            }
112
+            else {
113
+                content = [data dataUsingEncoding:NSUTF8StringEncoding];
114
+            }
115
+            if(append == YES) {
116
+                [fileHandle seekToEndOfFile];
117
+                [fileHandle writeData:content];
118
+                [fileHandle closeFile];
119
+            }
120
+            else {
121
+                [content writeToFile:path atomically:YES];
109 122
             }
110
-            else
111
-                [fileHandle writeData:[data dataUsingEncoding:NSUTF8StringEncoding]];
112
-            [fileHandle closeFile];
113 123
         }
114 124
         fm = nil;
115 125
         resolve([NSNull null]);
@@ -120,22 +130,38 @@ NSMutableDictionary *fileStreams = nil;
120 130
     }
121 131
 }
122 132
 
123
-+ (void) writeFileArray:(NSString *)path data:(NSArray *)data resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
133
++ (void) writeFileArray:(NSString *)path data:(NSArray *)data append:(BOOL)append resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
124 134
     @try {
125 135
         NSFileManager * fm = [NSFileManager defaultManager];
136
+        NSError * err = nil;
137
+        // check if the folder exists, if not exists, create folders recursively
138
+        // after the folders created, write data into the file
139
+        NSString * folder = [path stringByDeletingLastPathComponent];
140
+        if(![fm fileExistsAtPath:folder]) {
141
+            [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
142
+        }
126 143
         NSMutableData * fileContent = [NSMutableData alloc];
127 144
         // prevent stack overflow, alloc on heap
128 145
         char * bytes = (char*) malloc([data count]);
129 146
         for(int i = 0; i < data.count; i++) {
130 147
             bytes[i] = [[data objectAtIndex:i] charValue];
131 148
         }
132
-        // if append == NO
133
-//        BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
134 149
         [fileContent appendBytes:bytes length:data.count];
135
-        NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
136
-        [fileHandle seekToEndOfFile];
137
-        [fileHandle writeData:fileContent];
138
-        [fileHandle closeFile];
150
+        if(![fm fileExistsAtPath:path]) {
151
+            [fm createFileAtPath:path contents:fileContent attributes:NULL];
152
+        }
153
+        // if file exists, write file
154
+        else {
155
+            if(append == YES) {
156
+                NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
157
+                [fileHandle seekToEndOfFile];
158
+                [fileHandle writeData:fileContent];
159
+                [fileHandle closeFile];
160
+            }
161
+            else {
162
+                [fileContent writeToFile:path atomically:YES];
163
+            }
164
+        }
139 165
         free(bytes);
140 166
         fm = nil;
141 167
         resolve([NSNull null]);

+ 3
- 3
test/test-0.6.0.js View File

@@ -28,12 +28,12 @@ let prefix = ((Platform.OS === 'android') ? 'file://' : '')
28 28
 describe('writeFile test', (report, done) => {
29 29
   let path = dirs.DocumentDir + '/0.6.0-'+Date.now()+'/writeFileTest'+Date.now()
30 30
   let data = 'hellofrom'+Date.now()
31
-  fs.writeFile(path, 'utf8', data)
31
+  fs.writeFile(path, data)
32 32
     .then(() => fs.readFile(path, 'utf8'))
33 33
     .then((actual) => {
34 34
       report(<Assert key="utf8 content should correct" expect={data} actual={actual}/>)
35 35
       data += 'base64'
36
-      return fs.writeFile(path, 'base64', RNFetchBlob.base64.encode('base64'))
36
+      return fs.writeFile(path, RNFetchBlob.base64.encode('base64'), 'base64')
37 37
     })
38 38
     .then(() => fs.readFile(path, 'base64'))
39 39
     .then((actual) => {
@@ -41,7 +41,7 @@ describe('writeFile test', (report, done) => {
41 41
         expect={RNFetchBlob.base64.decode(RNFetchBlob.base64.encode(data))}
42 42
         actual={RNFetchBlob.base64.decode(actual)}/>)
43 43
       data += 'ascii'
44
-      return fs.writeFile(path, 'ascii', getASCIIArray('ascii'));
44
+      return fs.writeFile(path, getASCIIArray('ascii'), 'ascii');
45 45
     })
46 46
     .then(() => fs.readFile(path, 'ascii'))
47 47
     .then((actual) => {