Merge branch 'master' of github.com:itinance/react-native-fs
* 'master' of github.com:itinance/react-native-fs: (25 commits) fix touch() error on android Fixed Mtime Add missing flow annotations v2.5.2 (cocoapods related only) removed osx-version from Podspec added a note for cocoapods that we can't support it yet added a note for cocoapods that we can't support it yet Changes to the Podspec Changelog for README Version 2.5.0 - compat with RN 0.47.0 Added back for Backward-Compat but without @override Version bump 2.4.0 removed createJSModules method (RN 0.47 breaking change) Add `createJSModules()` to be compatible with latest React. Update SDK compile and build tools to version 26. update README add read method with lenght and position params add `touch` method for changing file timestamps Remove createJSModules from package pod file path error ...
This commit is contained in:
commit
bcf81df6f8
|
@ -13,6 +13,7 @@ var NativeAppEventEmitter = require('react-native').NativeAppEventEmitter; // i
|
|||
var DeviceEventEmitter = require('react-native').DeviceEventEmitter; // Android
|
||||
var base64 = require('base-64');
|
||||
var utf8 = require('utf8');
|
||||
var isIOS = require('react-native').Platform.OS === 'ios';
|
||||
|
||||
var RNFSFileTypeRegular = RNFSManager.RNFSFileTypeRegular;
|
||||
var RNFSFileTypeDirectory = RNFSManager.RNFSFileTypeDirectory;
|
||||
|
@ -60,6 +61,8 @@ type DownloadFileOptions = {
|
|||
headers?: Headers; // An object of headers to be passed to the server
|
||||
background?: boolean; // iOS only
|
||||
progressDivider?: number;
|
||||
readTimeout?: number;
|
||||
connectionTimeout?: number;
|
||||
begin?: (res: DownloadBeginCallbackResult) => void;
|
||||
progress?: (res: DownloadProgressCallbackResult) => void;
|
||||
};
|
||||
|
@ -265,6 +268,36 @@ var RNFS = {
|
|||
return readFileGeneric(filepath, encodingOrOptions, RNFSManager.readFile);
|
||||
},
|
||||
|
||||
read(filepath: string, length: number = 0, position: number = 0, encodingOrOptions?: any): Promise<string> {
|
||||
var options = {
|
||||
encoding: 'utf8'
|
||||
};
|
||||
|
||||
if (encodingOrOptions) {
|
||||
if (typeof encodingOrOptions === 'string') {
|
||||
options.encoding = encodingOrOptions;
|
||||
} else if (typeof encodingOrOptions === 'object') {
|
||||
options = encodingOrOptions;
|
||||
}
|
||||
}
|
||||
|
||||
return RNFSManager.read(normalizeFilePath(filepath), length, position).then((b64) => {
|
||||
var contents;
|
||||
|
||||
if (options.encoding === 'utf8') {
|
||||
contents = utf8.decode(base64.decode(b64));
|
||||
} else if (options.encoding === 'ascii') {
|
||||
contents = base64.decode(b64);
|
||||
} else if (options.encoding === 'base64') {
|
||||
contents = b64;
|
||||
} else {
|
||||
throw new Error('Invalid encoding type "' + String(options.encoding) + '"');
|
||||
}
|
||||
|
||||
return contents;
|
||||
});
|
||||
},
|
||||
|
||||
// Android only
|
||||
readFileAssets(filepath: string, encodingOrOptions?: any): Promise<string> {
|
||||
if (!RNFSManager.readFileAssets) {
|
||||
|
@ -397,6 +430,8 @@ var RNFS = {
|
|||
if (options.headers && typeof options.headers !== 'object') throw new Error('downloadFile: Invalid value for property `headers`');
|
||||
if (options.background && typeof options.background !== 'boolean') throw new Error('downloadFile: Invalid value for property `background`');
|
||||
if (options.progressDivider && typeof options.progressDivider !== 'number') throw new Error('downloadFile: Invalid value for property `progressDivider`');
|
||||
if (options.readTimeout && typeof options.readTimeout !== 'number') throw new Error('downloadFile: Invalid value for property `readTimeout`');
|
||||
if (options.connectionTimeout && typeof options.connectionTimeout !== 'number') throw new Error('downloadFile: Invalid value for property `connectionTimeout`');
|
||||
|
||||
var jobId = getJobId();
|
||||
var subscriptions = [];
|
||||
|
@ -415,7 +450,9 @@ var RNFS = {
|
|||
toFile: normalizeFilePath(options.toFile),
|
||||
headers: options.headers || {},
|
||||
background: !!options.background,
|
||||
progressDivider: options.progressDivider || 0
|
||||
progressDivider: options.progressDivider || 0,
|
||||
readTimeout: options.readTimeout || 15000,
|
||||
connectionTimeout: options.connectionTimeout || 5000
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -479,6 +516,20 @@ var RNFS = {
|
|||
};
|
||||
},
|
||||
|
||||
touch(filepath: string, mtime?: Date, ctime?: Date): Promise<void> {
|
||||
if (ctime && !(ctime instanceof Date)) throw new Error('touch: Invalid value for argument `ctime`');
|
||||
if (mtime && !(mtime instanceof Date)) throw new Error('touch: Invalid value for argument `mtime`');
|
||||
var ctimeTime = 0;
|
||||
if (isIOS) {
|
||||
ctimeTime = ctime && ctime.getTime();
|
||||
}
|
||||
return RNFSManager.touch(
|
||||
normalizeFilePath(filepath),
|
||||
mtime && mtime.getTime(),
|
||||
ctimeTime
|
||||
);
|
||||
},
|
||||
|
||||
MainBundlePath: RNFSManager.RNFSMainBundlePath,
|
||||
CachesDirectoryPath: RNFSManager.RNFSCachesDirectoryPath,
|
||||
DocumentDirectoryPath: RNFSManager.RNFSDocumentDirectoryPath,
|
||||
|
|
35
README.md
35
README.md
|
@ -2,11 +2,23 @@
|
|||
|
||||
Native filesystem access for react-native
|
||||
|
||||
## Changes for v2.5
|
||||
- breaking change for RN 0.47 at android (https://github.com/facebook/react-native/releases/tag/v0.47.0)
|
||||
|
||||
## Changes for v2.4
|
||||
- Made new thread for other native processes [ANDROID] (https://github.com/itinance/react-native-fs/commit/ad36b078db9728489155a55c1b7daa42ed191945) thx to [codesinghanoop](https://github.com/codesinghanoop)
|
||||
- Upgrade gradle build tools to 25 (https://github.com/itinance/react-native-fs/commit/239bccb9d56fe9308daafb86920ed29eb9e5cfe4) thx to [markusguenther](https://github.com/markusguenther)
|
||||
- Fixed Podfile Path-Error (https://github.com/itinance/react-native-fs/commit/9fd51e7e977400f3194c100af88b4c25e7510530) thx to [colorfulberry](https://github.com/colorfulberry)
|
||||
- Add read-method with length and position params (https://github.com/itinance/react-native-fs/commit/a39c22be81f0c1f2263dbe60f3cd6cfcc902d2ac) thx to [simitti](https://github.com/simitii)
|
||||
|
||||
|
||||
|
||||
## Changes for v2.3
|
||||
|
||||
- React-Native 0.40 is minimum required for compiling on iOS (otherwise install an older release, see below)
|
||||
- Access to iOS-based "assets-library" is now supported with `copyAssetsFileIOS`
|
||||
- `readDir` will return now creation- and modification-time of files as with `stat()` (thanks @Ignigena)
|
||||
- optional connectionTimeout and readTimeout-Settings on `downloadFile` for Android (thanks @drunksaint)
|
||||
|
||||
## Breaking change in v2.0
|
||||
|
||||
|
@ -43,18 +55,23 @@ At the command line, in your project folder, type:
|
|||
|
||||
Done! No need to worry about manually adding the library to your project.
|
||||
|
||||
### Adding with CocoaPods
|
||||
### ~~Adding with CocoaPods~~
|
||||
|
||||
Add the RNFS pod to your list of application pods in your Podfile, using the path from the Podfile to the installed module:
|
||||
Currently we don't support Cocoapods. If you are familiar with it, please feel free to submit PRs.
|
||||
More Info [here](https://github.com/itinance/react-native-fs/issues/308#issuecomment-319803126).
|
||||
|
||||
~~Add the RNFS pod to your list of application pods in your Podfile, using the path from the Podfile to the installed module:~~
|
||||
|
||||
~~
|
||||
```
|
||||
pod 'RNFS', :path => './node_modules/react-native-fs'
|
||||
pod 'RNFS', :path => '../node_modules/react-native-fs'
|
||||
```
|
||||
|
||||
Install pods as usual:
|
||||
```
|
||||
pod install
|
||||
```
|
||||
~~
|
||||
|
||||
### Adding Manually in XCode
|
||||
|
||||
|
@ -362,6 +379,12 @@ Reads the file at `path` and return contents. `encoding` can be one of `utf8` (d
|
|||
|
||||
Note: you will take quite a performance hit if you are reading big files
|
||||
|
||||
### `read(filepath: string, length = 0, position = 0, encodingOrOptions?: any): Promise<string>`
|
||||
|
||||
Reads `length` bytes from the given `position` of the file at `path` and returns contents. `encoding` can be one of `utf8` (default), `ascii`, `base64`. Use `base64` for reading binary files.
|
||||
|
||||
Note: reading big files piece by piece using this method may be useful in terms of performance.
|
||||
|
||||
### `readFileAssets(filepath:string, encoding?: string): Promise<string>`
|
||||
|
||||
Reads the file at `path` in the Android app's assets folder and return contents. `encoding` can be one of `utf8` (default), `ascii`, `base64`. Use `base64` for reading binary files.
|
||||
|
@ -440,6 +463,10 @@ Check in the Android assets folder if the item exists. `filepath` is the relativ
|
|||
|
||||
Reads the file at `path` and returns its checksum as determined by `algorithm`, which can be one of `md5`, `sha1`, `sha224`, `sha256`, `sha384`, `sha512`.
|
||||
|
||||
### `touch(filepath: string, mtime?: Date, ctime?: Date): Promise<string>`
|
||||
|
||||
Sets the modification timestamp `mtime` and creation timestamp `ctime` of the file at `filepath`. Setting `ctime` is only supported on iOS, android always sets both timestamps to `mtime`.
|
||||
|
||||
### `mkdir(filepath: string, options?: MkdirOptions): Promise<void>`
|
||||
|
||||
```
|
||||
|
@ -463,6 +490,8 @@ type DownloadFileOptions = {
|
|||
progressDivider?: number;
|
||||
begin?: (res: DownloadBeginCallbackResult) => void;
|
||||
progress?: (res: DownloadProgressCallbackResult) => void;
|
||||
connectionTimeout?: number // only supported on Android yet
|
||||
readTimeout?: number // only supported on Android yet
|
||||
};
|
||||
```
|
||||
```
|
||||
|
|
|
@ -9,12 +9,13 @@ Pod::Spec.new do |s|
|
|||
s.summary = pjson["description"]
|
||||
s.license = pjson["license"]
|
||||
s.author = { "Johannes Lumpe" => "johannes@lum.pe" }
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.tvos.deployment_target = '9.0'
|
||||
|
||||
s.ios.deployment_target = '9.0'
|
||||
|
||||
s.source = { :git => "https://github.com/itinance/react-native-fs", :tag => "v#{s.version}" }
|
||||
s.source_files = '*.{h,m}'
|
||||
s.preserve_paths = "**/*.js"
|
||||
|
||||
s.dependency 'React/Core'
|
||||
s.dependency 'React'
|
||||
|
||||
end
|
||||
|
|
|
@ -261,6 +261,51 @@ RCT_EXPORT_METHOD(readFile:(NSString *)filepath
|
|||
resolve(base64Content);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(read:(NSString *)filepath
|
||||
length: (NSInteger *)length
|
||||
position: (NSInteger *)position
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filepath];
|
||||
|
||||
if (!fileExists) {
|
||||
return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:&error];
|
||||
|
||||
if (error) {
|
||||
return [self reject:reject withError:error];
|
||||
}
|
||||
|
||||
if ([attributes objectForKey:NSFileType] == NSFileTypeDirectory) {
|
||||
return reject(@"EISDIR", @"EISDIR: illegal operation on a directory, read", nil);
|
||||
}
|
||||
|
||||
// Open the file handler.
|
||||
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:filepath];
|
||||
if (file == nil) {
|
||||
return reject(@"EISDIR", @"EISDIR: Could not open file for reading", nil);
|
||||
}
|
||||
|
||||
// Seek to the position if there is one.
|
||||
[file seekToFileOffset: (int)position];
|
||||
|
||||
NSData *content;
|
||||
if ((int)length > 0) {
|
||||
content = [file readDataOfLength: (int)length];
|
||||
} else {
|
||||
content = [file readDataToEndOfFile];
|
||||
}
|
||||
|
||||
NSString *base64Content = [content base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
|
||||
|
||||
resolve(base64Content);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(hash:(NSString *)filepath
|
||||
algorithm:(NSString *)algorithm
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
|
@ -685,6 +730,37 @@ RCT_EXPORT_METHOD(copyAssetsVideoIOS: (NSString *) imageUri
|
|||
resolve(destination);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(touch:(NSString*)filepath
|
||||
mtime:(NSDate *)mtime
|
||||
ctime:(NSDate *)ctime
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
BOOL exists = [manager fileExistsAtPath:filepath isDirectory:false];
|
||||
|
||||
if (!exists) {
|
||||
return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file, open '%@'", filepath], nil);
|
||||
}
|
||||
|
||||
NSMutableDictionary *attr = [NSMutableDictionary dictionary];
|
||||
|
||||
if (mtime) {
|
||||
[attr setValue:mtime forKey:NSFileModificationDate];
|
||||
}
|
||||
if (ctime) {
|
||||
[attr setValue:ctime forKey:NSFileCreationDate];
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
BOOL success = [manager setAttributes:attr ofItemAtPath:filepath error:&error];
|
||||
|
||||
if (!success) {
|
||||
return [self reject:reject withError:error];
|
||||
}
|
||||
|
||||
resolve(nil);
|
||||
}
|
||||
|
||||
|
||||
- (NSNumber *)dateToTimeIntervalNumber:(NSDate *)date
|
||||
|
|
|
@ -11,8 +11,8 @@ buildscript {
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.1"
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.0"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
|
|
|
@ -23,6 +23,8 @@ public class DownloadParams {
|
|||
public File dest;
|
||||
public ReadableMap headers;
|
||||
public float progressDivider;
|
||||
public int readTimeout;
|
||||
public int connectionTimeout;
|
||||
public OnTaskCompleted onTaskCompleted;
|
||||
public OnDownloadBegin onDownloadBegin;
|
||||
public OnDownloadProgress onDownloadProgress;
|
||||
|
|
|
@ -22,20 +22,23 @@ import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|||
public class Downloader extends AsyncTask<DownloadParams, int[], DownloadResult> {
|
||||
private DownloadParams mParam;
|
||||
private AtomicBoolean mAbort = new AtomicBoolean(false);
|
||||
DownloadResult res;
|
||||
|
||||
protected DownloadResult doInBackground(DownloadParams... params) {
|
||||
mParam = params[0];
|
||||
res = new DownloadResult();
|
||||
|
||||
DownloadResult res = new DownloadResult();
|
||||
|
||||
try {
|
||||
this.download(mParam, res);
|
||||
mParam.onTaskCompleted.onTaskCompleted(res);
|
||||
} catch (Exception ex) {
|
||||
res.exception = ex;
|
||||
mParam.onTaskCompleted.onTaskCompleted(res);
|
||||
return res;
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
download(mParam, res);
|
||||
mParam.onTaskCompleted.onTaskCompleted(res);
|
||||
} catch (Exception ex) {
|
||||
res.exception = ex;
|
||||
mParam.onTaskCompleted.onTaskCompleted(res);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -56,8 +59,8 @@ public class Downloader extends AsyncTask<DownloadParams, int[], DownloadResult>
|
|||
connection.setRequestProperty(key, value);
|
||||
}
|
||||
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(15000);
|
||||
connection.setConnectTimeout(param.connectionTimeout);
|
||||
connection.setReadTimeout(param.readTimeout);
|
||||
connection.connect();
|
||||
|
||||
int statusCode = connection.getResponseCode();
|
||||
|
|
|
@ -150,6 +150,35 @@ public class RNFSManager extends ReactContextBaseJavaModule {
|
|||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void read(String filepath, int length, int position, Promise promise){
|
||||
try {
|
||||
File file = new File(filepath);
|
||||
|
||||
if (file.isDirectory()) {
|
||||
rejectFileIsDirectory(promise);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
rejectFileNotFound(promise, filepath);
|
||||
return;
|
||||
}
|
||||
|
||||
FileInputStream inputStream = new FileInputStream(filepath);
|
||||
byte[] buffer = new byte[length];
|
||||
inputStream.skip(position);
|
||||
inputStream.read(buffer,0,length);
|
||||
|
||||
String base64Content = Base64.encodeToString(buffer, Base64.NO_WRAP);
|
||||
|
||||
promise.resolve(base64Content);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
reject(promise, filepath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void readFileAssets(String filepath, Promise promise) {
|
||||
InputStream stream = null;
|
||||
|
@ -283,7 +312,7 @@ public class RNFSManager extends ReactContextBaseJavaModule {
|
|||
for (File childFile : files) {
|
||||
WritableMap fileMap = Arguments.createMap();
|
||||
|
||||
fileMap.putInt("mtime", (int)childFile.lastModified());
|
||||
fileMap.putDouble("mtime", (double)childFile.lastModified()/1000);
|
||||
fileMap.putString("name", childFile.getName());
|
||||
fileMap.putString("path", childFile.getAbsolutePath());
|
||||
fileMap.putInt("size", (int)childFile.length());
|
||||
|
@ -631,6 +660,17 @@ public class RNFSManager extends ReactContextBaseJavaModule {
|
|||
promise.resolve(info);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void touch(String filepath, double mtime, double ctime, Promise promise) {
|
||||
try {
|
||||
File file = new File(filepath);
|
||||
promise.resolve(file.setLastModified((long) mtime));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
reject(promise, filepath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void reject(Promise promise, String filepath, Exception ex) {
|
||||
if (ex instanceof FileNotFoundException) {
|
||||
rejectFileNotFound(promise, filepath);
|
||||
|
|
|
@ -17,13 +17,14 @@ public class RNFSPackage implements ReactPackage {
|
|||
return modules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
||||
return Collections.emptyList();
|
||||
// deprecated >= RN 0.47.0
|
||||
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Arrays.<ViewManager>asList();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,5 +32,8 @@
|
|||
"flow-bin": "0.28.0",
|
||||
"react": "^15.4.2",
|
||||
"react-native": "^0.40.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": ">=0.40.0"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue