Browse Source

#27 add append option to writeFile API

Ben Hsieh 9 years ago
parent
commit
2a80b5b092

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

99
     }
99
     }
100
 
100
 
101
     @ReactMethod
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
     @ReactMethod
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
     @ReactMethod
111
     @ReactMethod

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

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

+ 28
- 3
src/fs.js View File

139
   return RNFetchBlob.readFile(path, encoding)
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
   if(typeof path !== 'string')
168
   if(typeof path !== 'string')
144
     return Promise.reject('Invalid argument "path" ')
169
     return Promise.reject('Invalid argument "path" ')
145
   if(encoding.toLocaleLowerCase() === 'ascii') {
170
   if(encoding.toLocaleLowerCase() === 'ascii') {
146
     if(!Array.isArray(data))
171
     if(!Array.isArray(data))
147
       Promise.reject(`Expected "data" is an Array when encoding is "ascii", however got ${typeof data}`)
172
       Promise.reject(`Expected "data" is an Array when encoding is "ascii", however got ${typeof data}`)
148
     else
173
     else
149
-      return RNFetchBlob.writeFileArray(path, data);
174
+      return RNFetchBlob.writeFileArray(path, data, true);
150
   } else {
175
   } else {
151
     if(typeof data !== 'string')
176
     if(typeof data !== 'string')
152
       Promise.reject(`Expected "data" is a String when encoding is "utf8" or "base64", however got ${typeof data}`)
177
       Promise.reject(`Expected "data" is a String when encoding is "utf8" or "base64", however got ${typeof data}`)
153
     else
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
     [RNFetchBlobFS readFile:path encoding:encoding resolver:resolve rejecter:reject];
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
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {
426
 RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) {

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

48
 + (BOOL) mkdir:(NSString *) path;
48
 + (BOOL) mkdir:(NSString *) path;
49
 + (NSDictionary *) stat:(NSString *) path error:(NSError **) error;
49
 + (NSDictionary *) stat:(NSString *) path error:(NSError **) error;
50
 + (BOOL) exists:(NSString *) path;
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
 + (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
53
 + (void) readFile:(NSString *)path encoding:(NSString *)encoding resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
54
 
54
 
55
 // constructor
55
 // constructor

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

84
     return tempPath;
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
     @try {
88
     @try {
89
         NSFileManager * fm = [NSFileManager defaultManager];
89
         NSFileManager * fm = [NSFileManager defaultManager];
90
         NSError * err = nil;
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
         NSString * folder = [path stringByDeletingLastPathComponent];
93
         NSString * folder = [path stringByDeletingLastPathComponent];
92
         if(![fm fileExistsAtPath:folder]) {
94
         if(![fm fileExistsAtPath:folder]) {
93
             [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
95
             [fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
94
         }
96
         }
97
+        // if file exists, write file by encoding and strategy
95
         if(![fm fileExistsAtPath:path]) {
98
         if(![fm fileExistsAtPath:path]) {
96
             if([[encoding lowercaseString] isEqualToString:@"base64"]){
99
             if([[encoding lowercaseString] isEqualToString:@"base64"]){
97
                 NSData * byteData = [[NSData alloc] initWithBase64EncodedString:data options:0];
100
                 NSData * byteData = [[NSData alloc] initWithBase64EncodedString:data options:0];
102
         }
105
         }
103
         else {
106
         else {
104
             NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
107
             NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
105
-            [fileHandle seekToEndOfFile];
108
+            NSData * content = nil;
106
             if([[encoding lowercaseString] isEqualToString:@"base64"]) {
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
         fm = nil;
124
         fm = nil;
115
         resolve([NSNull null]);
125
         resolve([NSNull null]);
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
     @try {
134
     @try {
125
         NSFileManager * fm = [NSFileManager defaultManager];
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
         NSMutableData * fileContent = [NSMutableData alloc];
143
         NSMutableData * fileContent = [NSMutableData alloc];
127
         // prevent stack overflow, alloc on heap
144
         // prevent stack overflow, alloc on heap
128
         char * bytes = (char*) malloc([data count]);
145
         char * bytes = (char*) malloc([data count]);
129
         for(int i = 0; i < data.count; i++) {
146
         for(int i = 0; i < data.count; i++) {
130
             bytes[i] = [[data objectAtIndex:i] charValue];
147
             bytes[i] = [[data objectAtIndex:i] charValue];
131
         }
148
         }
132
-        // if append == NO
133
-//        BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL];
134
         [fileContent appendBytes:bytes length:data.count];
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
         free(bytes);
165
         free(bytes);
140
         fm = nil;
166
         fm = nil;
141
         resolve([NSNull null]);
167
         resolve([NSNull null]);

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

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