Skip to content

Commit ad805da

Browse files
committed
Merge branch 'master' of github.com:itinance/react-native-fs
* 'master' of github.com:itinance/react-native-fs: [Podspec] [tvOS] Add target fixed property-names for created/ctime and modified/mtime in ReadDirItem Fix flowtype of date object in ReadDirItem Added write function for performing random access writes (node-js fs style)
2 parents e2ddc42 + 20b3915 commit ad805da

File tree

7 files changed

+202
-6
lines changed

7 files changed

+202
-6
lines changed

FS.common.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ type MkdirOptions = {
3131
};
3232

3333
type ReadDirItem = {
34-
created: date; // The creation date of the file (iOS only)
35-
modified: date; // The last modified date of the file
34+
ctime: ?Date; // The creation date of the file (iOS only)
35+
mtime: Date; // The last modified date of the file
3636
name: string; // The name of the item
3737
path: string; // The absolute path to the item
3838
size: string; // Size in bytes
@@ -276,7 +276,7 @@ var RNFS = {
276276

277277
// iOS only
278278
// Copies fotos from asset-library (camera-roll) to a specific location
279-
// with a given width or height
279+
// with a given width or height
280280
// @see: https://developer.apple.com/reference/photos/phimagemanager/1616964-requestimageforasset
281281
copyAssetsFileIOS(imageUri: string, destPath: string, width: number, height: number,
282282
scale : number = 1.0, compression : number = 1.0, resizeMode : string = 'contain' ): Promise<string> {
@@ -339,6 +339,38 @@ var RNFS = {
339339
return RNFSManager.appendFile(normalizeFilePath(filepath), b64);
340340
},
341341

342+
write(filepath: string, contents: string, position?: number, encodingOrOptions?: any): Promise<void> {
343+
var b64;
344+
345+
var options = {
346+
encoding: 'utf8'
347+
};
348+
349+
if (encodingOrOptions) {
350+
if (typeof encodingOrOptions === 'string') {
351+
options.encoding = encodingOrOptions;
352+
} else if (typeof encodingOrOptions === 'object') {
353+
options = encodingOrOptions;
354+
}
355+
}
356+
357+
if (options.encoding === 'utf8') {
358+
b64 = base64.encode(utf8.encode(contents));
359+
} else if (options.encoding === 'ascii') {
360+
b64 = base64.encode(contents);
361+
} else if (options.encoding === 'base64') {
362+
b64 = contents;
363+
} else {
364+
throw new Error('Invalid encoding type "' + options.encoding + '"');
365+
}
366+
367+
if (position === undefined) {
368+
position = -1;
369+
}
370+
371+
return RNFSManager.write(normalizeFilePath(filepath), b64, position).then(() => void 0);
372+
},
373+
342374
downloadFile(options: DownloadFileOptions): { jobId: number, promise: Promise<DownloadResult> } {
343375
if (typeof options !== 'object') throw new Error('downloadFile: Invalid value for argument `options`');
344376
if (typeof options.fromUrl !== 'string') throw new Error('downloadFile: Invalid value for property `fromUrl`');

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,10 @@ Write the `contents` to `filepath`. `encoding` can be one of `utf8` (default), `
378378

379379
Append the `contents` to `filepath`. `encoding` can be one of `utf8` (default), `ascii`, `base64`.
380380

381+
### `write(filepath: string, contents: string, position?: number, encoding?: string): Promise<void>`
382+
383+
Write the `contents` to `filepath` at the given random access position. When `position` is `undefined` or `-1` the contents is appended to the end of the file. `encoding` can be one of `utf8` (default), `ascii`, `base64`.
384+
381385
### `moveFile(filepath: string, destPath: string): Promise<void>`
382386

383387
Moves the file located at `filepath` to `destPath`. This is more performant than reading and then re-writing the file data because the move is done natively and the data doesn't have to be copied or cross the bridge.

RNFS.podspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Pod::Spec.new do |s|
99
s.summary = pjson["description"]
1010
s.license = pjson["license"]
1111
s.author = { "Johannes Lumpe" => "[email protected]" }
12-
s.platform = :ios, "8.0"
12+
s.ios.deployment_target = '8.0'
13+
s.tvos.deployment_target = '9.0'
1314
s.source = { :git => "https://github.com/itinance/react-native-fs", :tag => "v#{s.version}" }
1415
s.source_files = '*.{h,m}'
1516
s.preserve_paths = "**/*.js"

RNFS.xcodeproj/project.pbxproj

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,26 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
645644281EB8DAA100672408 /* NSArray+Map.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */; };
11+
645644291EB8DAA100672408 /* RNFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E59BDE1ADD662800ACA28A /* RNFSManager.m */; };
12+
6456442A1EB8DAA100672408 /* Downloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF740761C033A2E0057A1E7 /* Downloader.m */; };
13+
6456442B1EB8DAA100672408 /* Uploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BB364CB1CDA130000435A01 /* Uploader.m */; };
1014
8BB364CC1CDA130000435A01 /* Uploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BB364CB1CDA130000435A01 /* Uploader.m */; };
1115
8BF740771C033A2E0057A1E7 /* Downloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF740761C033A2E0057A1E7 /* Downloader.m */; };
1216
F1E59BDF1ADD662800ACA28A /* RNFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E59BDE1ADD662800ACA28A /* RNFSManager.m */; };
1317
F1EB08BB1AFD0E6A008F8F2B /* NSArray+Map.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */; };
1418
/* End PBXBuildFile section */
1519

1620
/* Begin PBXCopyFilesBuildPhase section */
21+
6456441D1EB8DA9100672408 /* CopyFiles */ = {
22+
isa = PBXCopyFilesBuildPhase;
23+
buildActionMask = 2147483647;
24+
dstPath = "include/$(PRODUCT_NAME)";
25+
dstSubfolderSpec = 16;
26+
files = (
27+
);
28+
runOnlyForDeploymentPostprocessing = 0;
29+
};
1730
F12AFB991ADAF8F800E0535D /* CopyFiles */ = {
1831
isa = PBXCopyFilesBuildPhase;
1932
buildActionMask = 2147483647;
@@ -26,6 +39,7 @@
2639
/* End PBXCopyFilesBuildPhase section */
2740

2841
/* Begin PBXFileReference section */
42+
6456441F1EB8DA9100672408 /* libRNFS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFS.a; sourceTree = BUILT_PRODUCTS_DIR; };
2943
8BB364CA1CDA130000435A01 /* Uploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uploader.h; sourceTree = "<group>"; };
3044
8BB364CB1CDA130000435A01 /* Uploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Uploader.m; sourceTree = "<group>"; };
3145
8BF740751C033A2E0057A1E7 /* Downloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Downloader.h; sourceTree = "<group>"; };
@@ -38,6 +52,13 @@
3852
/* End PBXFileReference section */
3953

4054
/* Begin PBXFrameworksBuildPhase section */
55+
6456441C1EB8DA9100672408 /* Frameworks */ = {
56+
isa = PBXFrameworksBuildPhase;
57+
buildActionMask = 2147483647;
58+
files = (
59+
);
60+
runOnlyForDeploymentPostprocessing = 0;
61+
};
4162
F12AFB981ADAF8F800E0535D /* Frameworks */ = {
4263
isa = PBXFrameworksBuildPhase;
4364
buildActionMask = 2147483647;
@@ -67,13 +88,31 @@
6788
isa = PBXGroup;
6889
children = (
6990
F12AFB9B1ADAF8F800E0535D /* libRNFS.a */,
91+
6456441F1EB8DA9100672408 /* libRNFS.a */,
7092
);
7193
name = Products;
7294
sourceTree = "<group>";
7395
};
7496
/* End PBXGroup section */
7597

7698
/* Begin PBXNativeTarget section */
99+
6456441E1EB8DA9100672408 /* RNFS-tvOS */ = {
100+
isa = PBXNativeTarget;
101+
buildConfigurationList = 645644271EB8DA9100672408 /* Build configuration list for PBXNativeTarget "RNFS-tvOS" */;
102+
buildPhases = (
103+
6456441B1EB8DA9100672408 /* Sources */,
104+
6456441C1EB8DA9100672408 /* Frameworks */,
105+
6456441D1EB8DA9100672408 /* CopyFiles */,
106+
);
107+
buildRules = (
108+
);
109+
dependencies = (
110+
);
111+
name = "RNFS-tvOS";
112+
productName = "RNFS-tvOS";
113+
productReference = 6456441F1EB8DA9100672408 /* libRNFS.a */;
114+
productType = "com.apple.product-type.library.static";
115+
};
77116
F12AFB9A1ADAF8F800E0535D /* RNFS */ = {
78117
isa = PBXNativeTarget;
79118
buildConfigurationList = F12AFBAF1ADAF8F800E0535D /* Build configuration list for PBXNativeTarget "RNFS" */;
@@ -100,6 +139,10 @@
100139
LastUpgradeCheck = 0630;
101140
ORGANIZATIONNAME = "Johannes Lumpe";
102141
TargetAttributes = {
142+
6456441E1EB8DA9100672408 = {
143+
CreatedOnToolsVersion = 8.3.2;
144+
ProvisioningStyle = Automatic;
145+
};
103146
F12AFB9A1ADAF8F800E0535D = {
104147
CreatedOnToolsVersion = 6.3;
105148
};
@@ -118,11 +161,23 @@
118161
projectRoot = "";
119162
targets = (
120163
F12AFB9A1ADAF8F800E0535D /* RNFS */,
164+
6456441E1EB8DA9100672408 /* RNFS-tvOS */,
121165
);
122166
};
123167
/* End PBXProject section */
124168

125169
/* Begin PBXSourcesBuildPhase section */
170+
6456441B1EB8DA9100672408 /* Sources */ = {
171+
isa = PBXSourcesBuildPhase;
172+
buildActionMask = 2147483647;
173+
files = (
174+
645644281EB8DAA100672408 /* NSArray+Map.m in Sources */,
175+
645644291EB8DAA100672408 /* RNFSManager.m in Sources */,
176+
6456442A1EB8DAA100672408 /* Downloader.m in Sources */,
177+
6456442B1EB8DAA100672408 /* Uploader.m in Sources */,
178+
);
179+
runOnlyForDeploymentPostprocessing = 0;
180+
};
126181
F12AFB971ADAF8F800E0535D /* Sources */ = {
127182
isa = PBXSourcesBuildPhase;
128183
buildActionMask = 2147483647;
@@ -137,6 +192,40 @@
137192
/* End PBXSourcesBuildPhase section */
138193

139194
/* Begin XCBuildConfiguration section */
195+
645644251EB8DA9100672408 /* Debug */ = {
196+
isa = XCBuildConfiguration;
197+
buildSettings = {
198+
CLANG_ANALYZER_NONNULL = YES;
199+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
200+
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
201+
CLANG_WARN_INFINITE_RECURSION = YES;
202+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
203+
DEBUG_INFORMATION_FORMAT = dwarf;
204+
ENABLE_TESTABILITY = YES;
205+
OTHER_LDFLAGS = "-ObjC";
206+
PRODUCT_NAME = RNFS;
207+
SDKROOT = appletvos;
208+
SKIP_INSTALL = YES;
209+
TVOS_DEPLOYMENT_TARGET = 10.2;
210+
};
211+
name = Debug;
212+
};
213+
645644261EB8DA9100672408 /* Release */ = {
214+
isa = XCBuildConfiguration;
215+
buildSettings = {
216+
CLANG_ANALYZER_NONNULL = YES;
217+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
218+
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
219+
CLANG_WARN_INFINITE_RECURSION = YES;
220+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
221+
OTHER_LDFLAGS = "-ObjC";
222+
PRODUCT_NAME = RNFS;
223+
SDKROOT = appletvos;
224+
SKIP_INSTALL = YES;
225+
TVOS_DEPLOYMENT_TARGET = 10.2;
226+
};
227+
name = Release;
228+
};
140229
F12AFBAD1ADAF8F800E0535D /* Debug */ = {
141230
isa = XCBuildConfiguration;
142231
buildSettings = {
@@ -250,6 +339,14 @@
250339
/* End XCBuildConfiguration section */
251340

252341
/* Begin XCConfigurationList section */
342+
645644271EB8DA9100672408 /* Build configuration list for PBXNativeTarget "RNFS-tvOS" */ = {
343+
isa = XCConfigurationList;
344+
buildConfigurations = (
345+
645644251EB8DA9100672408 /* Debug */,
346+
645644261EB8DA9100672408 /* Release */,
347+
);
348+
defaultConfigurationIsVisible = 0;
349+
};
253350
F12AFB961ADAF8F800E0535D /* Build configuration list for PBXProject "RNFS" */ = {
254351
isa = XCConfigurationList;
255352
buildConfigurations = (

RNFSManager.m

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,43 @@ - (dispatch_queue_t)methodQueue
147147
}
148148
}
149149

150+
RCT_EXPORT_METHOD(write:(NSString *)filepath
151+
contents:(NSString *)base64Content
152+
position:(NSInteger)position
153+
resolver:(RCTPromiseResolveBlock)resolve
154+
rejecter:(RCTPromiseRejectBlock)reject)
155+
{
156+
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters];
157+
158+
NSFileManager *fM = [NSFileManager defaultManager];
159+
160+
if (![fM fileExistsAtPath:filepath])
161+
{
162+
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:nil];
163+
164+
if (!success) {
165+
return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
166+
} else {
167+
return resolve(nil);
168+
}
169+
}
170+
171+
@try {
172+
NSFileHandle *fH = [NSFileHandle fileHandleForUpdatingAtPath:filepath];
173+
174+
if (position >= 0) {
175+
[fH seekToFileOffset:position];
176+
} else {
177+
[fH seekToEndOfFile];
178+
}
179+
[fH writeData:data];
180+
181+
return resolve(nil);
182+
} @catch (NSException *e) {
183+
return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: error writing file: '%@'", filepath], nil);
184+
}
185+
}
186+
150187
RCT_EXPORT_METHOD(unlink:(NSString*)filepath
151188
resolver:(RCTPromiseResolveBlock)resolve
152189
rejecter:(RCTPromiseRejectBlock)reject)

android/src/main/java/com/rnfs/RNFSManager.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.io.IOException;
2727
import java.io.InputStream;
2828
import java.io.OutputStream;
29+
import java.io.RandomAccessFile;
2930
import java.net.URL;
3031
import java.security.MessageDigest;
3132
import java.util.HashMap;
@@ -87,6 +88,29 @@ public void appendFile(String filepath, String base64Content, Promise promise) {
8788
}
8889
}
8990

91+
@ReactMethod
92+
public void write(String filepath, String base64Content, int position, Promise promise) {
93+
try {
94+
byte[] bytes = Base64.decode(base64Content, Base64.DEFAULT);
95+
96+
if (position < 0) {
97+
FileOutputStream outputStream = new FileOutputStream(filepath, true);
98+
outputStream.write(bytes);
99+
outputStream.close();
100+
} else {
101+
RandomAccessFile file = new RandomAccessFile(filepath, "rw");
102+
file.seek(position);
103+
file.write(bytes);
104+
file.close();
105+
}
106+
107+
promise.resolve(null);
108+
} catch (Exception ex) {
109+
ex.printStackTrace();
110+
reject(promise, filepath, ex);
111+
}
112+
}
113+
90114
@ReactMethod
91115
public void exists(String filepath, Promise promise) {
92116
try {

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "Native filesystem access for react-native",
55
"main": "FS.common.js",
66
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
7+
"test": "echo \"Error: no test specified\" && exit 1",
8+
"flow": "flow; test $? -eq 0 -o $? -eq 2"
89
},
910
"repository": {
1011
"type": "git",
@@ -28,7 +29,7 @@
2829
"utf8": "^2.1.1"
2930
},
3031
"devDependencies": {
31-
"flow-bin": "0.27.0",
32+
"flow-bin": "0.28.0",
3233
"react": "^15.4.2",
3334
"react-native": "^0.40.0"
3435
}

0 commit comments

Comments
 (0)