Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
b157767157
|
@ -88,6 +88,10 @@
|
|||
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
|
||||
{
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)downloadTask.response;
|
||||
if (!_statusCode) {
|
||||
_statusCode = [NSNumber numberWithLong:httpResponse.statusCode];
|
||||
}
|
||||
NSURL *destURL = [NSURL fileURLWithPath:_params.toFile];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSError *error = nil;
|
||||
|
@ -102,7 +106,9 @@
|
|||
|
||||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
|
||||
{
|
||||
return error ? _params.errorCallback(error) : nil;
|
||||
if (error && error.code != -999) {
|
||||
_params.errorCallback(error);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopDownload
|
||||
|
|
45
FS.common.js
45
FS.common.js
|
@ -31,6 +31,8 @@ type MkdirOptions = {
|
|||
};
|
||||
|
||||
type ReadDirItem = {
|
||||
ctime: ?Date; // The creation date of the file (iOS only)
|
||||
mtime: Date; // The last modified date of the file
|
||||
name: string; // The name of the item
|
||||
path: string; // The absolute path to the item
|
||||
size: string; // Size in bytes
|
||||
|
@ -159,6 +161,8 @@ function readFileGeneric(filepath: string, encodingOrOptions:?string, command: F
|
|||
function readDirGeneric(dirpath: string, command: Function) {
|
||||
return command(normalizeFilePath(dirpath)).then(files => {
|
||||
return files.map(file => ({
|
||||
ctime: file.ctime && new Date(file.ctime * 1000) || null,
|
||||
mtime: new Date(file.mtime * 1000),
|
||||
name: file.name,
|
||||
path: file.path,
|
||||
size: file.size,
|
||||
|
@ -274,6 +278,15 @@ var RNFS = {
|
|||
return RNFSManager.copyFileAssets(normalizeFilePath(filepath), normalizeFilePath(destPath)).then(() => void 0);
|
||||
},
|
||||
|
||||
// iOS only
|
||||
// Copies fotos from asset-library (camera-roll) to a specific location
|
||||
// with a given width or height
|
||||
// @see: https://developer.apple.com/reference/photos/phimagemanager/1616964-requestimageforasset
|
||||
copyAssetsFileIOS(imageUri: string, destPath: string, width: number, height: number,
|
||||
scale : number = 1.0, compression : number = 1.0, resizeMode : string = 'contain' ): Promise<string> {
|
||||
return RNFSManager.copyAssetsFileIOS(imageUri, destPath, width, height, scale, compression, resizeMode );
|
||||
},
|
||||
|
||||
writeFile(filepath: string, contents: string, encodingOrOptions?: any): Promise<void> {
|
||||
var b64;
|
||||
|
||||
|
@ -330,6 +343,38 @@ var RNFS = {
|
|||
return RNFSManager.appendFile(normalizeFilePath(filepath), b64);
|
||||
},
|
||||
|
||||
write(filepath: string, contents: string, position?: number, encodingOrOptions?: any): Promise<void> {
|
||||
var b64;
|
||||
|
||||
var options = {
|
||||
encoding: 'utf8'
|
||||
};
|
||||
|
||||
if (encodingOrOptions) {
|
||||
if (typeof encodingOrOptions === 'string') {
|
||||
options.encoding = encodingOrOptions;
|
||||
} else if (typeof encodingOrOptions === 'object') {
|
||||
options = encodingOrOptions;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.encoding === 'utf8') {
|
||||
b64 = base64.encode(utf8.encode(contents));
|
||||
} else if (options.encoding === 'ascii') {
|
||||
b64 = base64.encode(contents);
|
||||
} else if (options.encoding === 'base64') {
|
||||
b64 = contents;
|
||||
} else {
|
||||
throw new Error('Invalid encoding type "' + options.encoding + '"');
|
||||
}
|
||||
|
||||
if (position === undefined) {
|
||||
position = -1;
|
||||
}
|
||||
|
||||
return RNFSManager.write(normalizeFilePath(filepath), b64, position).then(() => void 0);
|
||||
},
|
||||
|
||||
downloadFile(options: DownloadFileOptions): { jobId: number, promise: Promise<DownloadResult> } {
|
||||
if (typeof options !== 'object') throw new Error('downloadFile: Invalid value for argument `options`');
|
||||
if (typeof options.fromUrl !== 'string') throw new Error('downloadFile: Invalid value for property `fromUrl`');
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#if __has_include("RCTRootView.h")
|
||||
#import "RCTRootView.h"
|
||||
#else
|
||||
#import <React/RCTRootView.h>
|
||||
#endif
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
|
40
README.md
40
README.md
|
@ -2,7 +2,13 @@
|
|||
|
||||
Native filesystem access for react-native
|
||||
|
||||
## Breaking change in v2.x
|
||||
## 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)
|
||||
|
||||
## Breaking change in v2.0
|
||||
|
||||
- Removed attributes from `writeFile` and `appendFile` for iOS / Android consistency
|
||||
- `downloadFile` takes `options` object rather than parameters
|
||||
|
@ -26,6 +32,9 @@ npm install react-native-fs --save
|
|||
npm install react-native-fs@2.0.1-rc.2 --save
|
||||
```
|
||||
|
||||
As @a-koka pointed out, you should then update your package.json to
|
||||
`"react-native-fs": "2.0.1-rc.2"` (without the tilde)
|
||||
|
||||
### Adding automatically with react-native link
|
||||
|
||||
At the command line, in your project folder, type:
|
||||
|
@ -284,6 +293,7 @@ The following constants are available on the `RNFS` export:
|
|||
- `CachesDirectoryPath` (`String`) The absolute path to the caches directory
|
||||
- `DocumentDirectoryPath` (`String`) The absolute path to the document directory
|
||||
- `TemporaryDirectoryPath` (`String`) The absolute path to the temporary directory (iOS only)
|
||||
- `LibraryDirectoryPath` (`String`) The absolute path to the NSLibraryDirectory (iOS only)
|
||||
- `ExternalDirectoryPath` (`String`) The absolute path to the external files, shared directory (android only)
|
||||
- `ExternalStorageDirectoryPath` (`String`) The absolute path to the external storage, shared directory (android only)
|
||||
|
||||
|
@ -295,6 +305,8 @@ The returned promise resolves with an array of objects with the following proper
|
|||
|
||||
```
|
||||
type ReadDirItem = {
|
||||
ctime: date; // The creation date of the file (iOS only)
|
||||
mtime: date; // The last modified date of the file
|
||||
name: string; // The name of the item
|
||||
path: string; // The absolute path to the item
|
||||
size: string; // Size in bytes
|
||||
|
@ -335,8 +347,8 @@ The promise resolves with an object with the following properties:
|
|||
|
||||
```
|
||||
type StatResult = {
|
||||
name: string; // The name of the item
|
||||
path: string; // The absolute path to the item
|
||||
ctime: date; // The creation date of the file
|
||||
mtime: date; // The last modified date of the file
|
||||
size: string; // Size in bytes
|
||||
mode: number; // UNIX file mode
|
||||
isFile: () => boolean; // Is the file just a file?
|
||||
|
@ -366,6 +378,10 @@ Write the `contents` to `filepath`. `encoding` can be one of `utf8` (default), `
|
|||
|
||||
Append the `contents` to `filepath`. `encoding` can be one of `utf8` (default), `ascii`, `base64`.
|
||||
|
||||
### `write(filepath: string, contents: string, position?: number, encoding?: string): Promise<void>`
|
||||
|
||||
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`.
|
||||
|
||||
### `moveFile(filepath: string, destPath: string): Promise<void>`
|
||||
|
||||
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.
|
||||
|
@ -378,10 +394,20 @@ Note: On Android copyFile will overwrite `destPath` if it already exists. On iOS
|
|||
|
||||
### `copyFileAssets(filepath: string, destPath: string): Promise<void>`
|
||||
|
||||
Copies the file at `filepath ` in the Android app's assets folder and copies it to the given `destPath ` path.
|
||||
Copies the file at `filepath` in the Android app's assets folder and copies it to the given `destPath ` path.
|
||||
|
||||
Note: Android only. Will overwrite destPath if it already exists
|
||||
|
||||
### `copyAssetsFileIOS(imageUri: string, destPath: string, width: number, height: number, scale : number = 1.0, compression : number = 1.0, resizeMode : string = 'contain' ): Promise<string>`
|
||||
|
||||
iOS-ony: copies a file from camera-roll, that is prefixed with "assets-library://asset/asset.JPG?..."
|
||||
to a specific destination. It will download the original from iCloud if necessary.
|
||||
If width and height is > 0, the image will be resized to a specific size and a specific compression rate.
|
||||
If scale is below 1, the image will be scaled according to the scale-factor (between 0.0 and 1.0)
|
||||
The resizeMode is also considered.
|
||||
Further information: https://developer.apple.com/reference/photos/phimagemanager/1616964-requestimageforasset
|
||||
The promise will on success return the final destination of the file, as it was defined in the destPath-parameter.
|
||||
|
||||
### `unlink(filepath: string): Promise<void>`
|
||||
|
||||
Unlinks the item at `filepath`. If the item does not exist, an error will be thrown.
|
||||
|
@ -465,10 +491,12 @@ If `progressDivider` = 0, you will receive all `progressCallback` calls, default
|
|||
(IOS only): `options.background` (`Boolean`) - Whether to continue downloads when the app is not focused (default: `false`)
|
||||
This option is currently only available for iOS, and you must [enable
|
||||
background fetch](https://www.objc.io/issues/5-ios7/multitasking/#background-fetch<Paste>)
|
||||
for your project in XCode.
|
||||
for your project in XCode. You only need to enable background fetch in `Info.plist` and set
|
||||
the fetch interval in `didFinishLaunchingWithOptions`. The `performFetchWithCompletionHandler`
|
||||
callback is handled by RNFS.
|
||||
|
||||
|
||||
### `stopDownload(jobId: number): Promise<void>`
|
||||
### `stopDownload(jobId: number): void`
|
||||
|
||||
Abort the current download job with this ID. The partial file will remain on the filesystem.
|
||||
|
||||
|
|
|
@ -5,12 +5,13 @@ Pod::Spec.new do |s|
|
|||
|
||||
s.name = "RNFS"
|
||||
s.version = pjson["version"]
|
||||
s.homepage = "https://github.com/johanneslumpe/react-native-fs"
|
||||
s.homepage = "https://github.com/itinance/react-native-fs"
|
||||
s.summary = pjson["description"]
|
||||
s.license = pjson["license"]
|
||||
s.author = { "Johannes Lumpe" => "johannes@lum.pe" }
|
||||
s.platform = :ios, "7.0"
|
||||
s.source = { :git => "https://github.com/johanneslumpe/react-native-fs", :tag => "#{s.version}" }
|
||||
s.ios.deployment_target = '8.0'
|
||||
s.tvos.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"
|
||||
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
645644281EB8DAA100672408 /* NSArray+Map.m in Sources */ = {isa = PBXBuildFile; fileRef = F1EB08BA1AFD0E6A008F8F2B /* NSArray+Map.m */; };
|
||||
645644291EB8DAA100672408 /* RNFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E59BDE1ADD662800ACA28A /* RNFSManager.m */; };
|
||||
6456442A1EB8DAA100672408 /* Downloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF740761C033A2E0057A1E7 /* Downloader.m */; };
|
||||
6456442B1EB8DAA100672408 /* Uploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BB364CB1CDA130000435A01 /* Uploader.m */; };
|
||||
8BB364CC1CDA130000435A01 /* Uploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BB364CB1CDA130000435A01 /* Uploader.m */; };
|
||||
8BF740771C033A2E0057A1E7 /* Downloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BF740761C033A2E0057A1E7 /* Downloader.m */; };
|
||||
F1E59BDF1ADD662800ACA28A /* RNFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E59BDE1ADD662800ACA28A /* RNFSManager.m */; };
|
||||
|
@ -14,6 +18,15 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
6456441D1EB8DA9100672408 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F12AFB991ADAF8F800E0535D /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -26,6 +39,7 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
6456441F1EB8DA9100672408 /* libRNFS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFS.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8BB364CA1CDA130000435A01 /* Uploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uploader.h; sourceTree = "<group>"; };
|
||||
8BB364CB1CDA130000435A01 /* Uploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Uploader.m; sourceTree = "<group>"; };
|
||||
8BF740751C033A2E0057A1E7 /* Downloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Downloader.h; sourceTree = "<group>"; };
|
||||
|
@ -38,6 +52,13 @@
|
|||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
6456441C1EB8DA9100672408 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F12AFB981ADAF8F800E0535D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -67,6 +88,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
F12AFB9B1ADAF8F800E0535D /* libRNFS.a */,
|
||||
6456441F1EB8DA9100672408 /* libRNFS.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -74,6 +96,23 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
6456441E1EB8DA9100672408 /* RNFS-tvOS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 645644271EB8DA9100672408 /* Build configuration list for PBXNativeTarget "RNFS-tvOS" */;
|
||||
buildPhases = (
|
||||
6456441B1EB8DA9100672408 /* Sources */,
|
||||
6456441C1EB8DA9100672408 /* Frameworks */,
|
||||
6456441D1EB8DA9100672408 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "RNFS-tvOS";
|
||||
productName = "RNFS-tvOS";
|
||||
productReference = 6456441F1EB8DA9100672408 /* libRNFS.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
F12AFB9A1ADAF8F800E0535D /* RNFS */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F12AFBAF1ADAF8F800E0535D /* Build configuration list for PBXNativeTarget "RNFS" */;
|
||||
|
@ -100,6 +139,10 @@
|
|||
LastUpgradeCheck = 0630;
|
||||
ORGANIZATIONNAME = "Johannes Lumpe";
|
||||
TargetAttributes = {
|
||||
6456441E1EB8DA9100672408 = {
|
||||
CreatedOnToolsVersion = 8.3.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
F12AFB9A1ADAF8F800E0535D = {
|
||||
CreatedOnToolsVersion = 6.3;
|
||||
};
|
||||
|
@ -118,11 +161,23 @@
|
|||
projectRoot = "";
|
||||
targets = (
|
||||
F12AFB9A1ADAF8F800E0535D /* RNFS */,
|
||||
6456441E1EB8DA9100672408 /* RNFS-tvOS */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
6456441B1EB8DA9100672408 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
645644281EB8DAA100672408 /* NSArray+Map.m in Sources */,
|
||||
645644291EB8DAA100672408 /* RNFSManager.m in Sources */,
|
||||
6456442A1EB8DAA100672408 /* Downloader.m in Sources */,
|
||||
6456442B1EB8DAA100672408 /* Uploader.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F12AFB971ADAF8F800E0535D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -137,6 +192,40 @@
|
|||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
645644251EB8DA9100672408 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = RNFS;
|
||||
SDKROOT = appletvos;
|
||||
SKIP_INSTALL = YES;
|
||||
TVOS_DEPLOYMENT_TARGET = 10.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
645644261EB8DA9100672408 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = RNFS;
|
||||
SDKROOT = appletvos;
|
||||
SKIP_INSTALL = YES;
|
||||
TVOS_DEPLOYMENT_TARGET = 10.2;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F12AFBAD1ADAF8F800E0535D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
@ -250,6 +339,14 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
645644271EB8DA9100672408 /* Build configuration list for PBXNativeTarget "RNFS-tvOS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
645644251EB8DA9100672408 /* Debug */,
|
||||
645644261EB8DA9100672408 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
};
|
||||
F12AFB961ADAF8F800E0535D /* Build configuration list for PBXProject "RNFS" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
131
RNFSManager.m
131
RNFSManager.m
|
@ -7,12 +7,18 @@
|
|||
//
|
||||
|
||||
#import "RNFSManager.h"
|
||||
#import <React/RCTBridge.h>
|
||||
|
||||
#import "NSArray+Map.h"
|
||||
#import "Downloader.h"
|
||||
#import "Uploader.h"
|
||||
|
||||
#import <React/RCTEventDispatcher.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <React/RCTImageLoader.h>
|
||||
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
#import <Photos/Photos.h>
|
||||
|
||||
|
||||
@interface RNFSManager()
|
||||
|
||||
|
@ -46,6 +52,8 @@ RCT_EXPORT_METHOD(readDir:(NSString *)dirPath
|
|||
NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:nil];
|
||||
|
||||
return @{
|
||||
@"ctime": [self dateToTimeIntervalNumber:(NSDate *)[attributes objectForKey:NSFileCreationDate]],
|
||||
@"mtime": [self dateToTimeIntervalNumber:(NSDate *)[attributes objectForKey:NSFileModificationDate]],
|
||||
@"name": obj,
|
||||
@"path": path,
|
||||
@"size": [attributes objectForKey:NSFileSize],
|
||||
|
@ -139,6 +147,43 @@ RCT_EXPORT_METHOD(appendFile:(NSString *)filepath
|
|||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(write:(NSString *)filepath
|
||||
contents:(NSString *)base64Content
|
||||
position:(NSInteger)position
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters];
|
||||
|
||||
NSFileManager *fM = [NSFileManager defaultManager];
|
||||
|
||||
if (![fM fileExistsAtPath:filepath])
|
||||
{
|
||||
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:nil];
|
||||
|
||||
if (!success) {
|
||||
return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
|
||||
} else {
|
||||
return resolve(nil);
|
||||
}
|
||||
}
|
||||
|
||||
@try {
|
||||
NSFileHandle *fH = [NSFileHandle fileHandleForUpdatingAtPath:filepath];
|
||||
|
||||
if (position >= 0) {
|
||||
[fH seekToFileOffset:position];
|
||||
} else {
|
||||
[fH seekToEndOfFile];
|
||||
}
|
||||
[fH writeData:data];
|
||||
|
||||
return resolve(nil);
|
||||
} @catch (NSException *e) {
|
||||
return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: error writing file: '%@'", filepath], nil);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(unlink:(NSString*)filepath
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
@ -508,6 +553,90 @@ RCT_EXPORT_METHOD(getFSInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromise
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* iOS Only: copy images from the assets-library (camera-roll) to a specific path, asuming
|
||||
* JPEG-Images. Video-Support will follow up, not implemented yet.
|
||||
*
|
||||
* It is also supported to scale the image via scale-factor (0.0-1.0) or with a specific
|
||||
* width and height. Also the resizeMode will be considered.
|
||||
*/
|
||||
RCT_EXPORT_METHOD(copyAssetsFileIOS: (NSString *) imageUri
|
||||
toFilepath: (NSString *) destination
|
||||
width: (NSInteger) width
|
||||
height: (NSInteger) height
|
||||
scale: (CGFloat) scale
|
||||
compression: (CGFloat) compression
|
||||
resizeMode: (RCTResizeMode) resizeMode
|
||||
resolver: (RCTPromiseResolveBlock) resolve
|
||||
rejecter: (RCTPromiseRejectBlock) reject)
|
||||
|
||||
{
|
||||
CGSize size = CGSizeMake(width, height);
|
||||
|
||||
NSURL* url = [NSURL URLWithString:imageUri];
|
||||
PHFetchResult *results = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
|
||||
|
||||
if (results.count == 0) {
|
||||
NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", imageUri];
|
||||
|
||||
NSMutableDictionary* details = [NSMutableDictionary dictionary];
|
||||
[details setValue:errorText forKey:NSLocalizedDescriptionKey];
|
||||
NSError *error = [NSError errorWithDomain:@"RNFS" code:500 userInfo:details];
|
||||
[self reject: reject withError:error];
|
||||
return;
|
||||
}
|
||||
|
||||
PHAsset *asset = [results firstObject];
|
||||
PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];
|
||||
|
||||
// Allow us to fetch images from iCloud
|
||||
imageOptions.networkAccessAllowed = YES;
|
||||
|
||||
|
||||
// Note: PhotoKit defaults to a deliveryMode of PHImageRequestOptionsDeliveryModeOpportunistic
|
||||
// which means it may call back multiple times - we probably don't want that
|
||||
imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
|
||||
|
||||
BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);
|
||||
CGSize targetSize;
|
||||
if (useMaximumSize) {
|
||||
targetSize = PHImageManagerMaximumSize;
|
||||
imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
|
||||
} else {
|
||||
targetSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
|
||||
imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
|
||||
}
|
||||
|
||||
PHImageContentMode contentMode = PHImageContentModeAspectFill;
|
||||
if (resizeMode == RCTResizeModeContain) {
|
||||
contentMode = PHImageContentModeAspectFit;
|
||||
}
|
||||
|
||||
// PHImageRequestID requestID =
|
||||
[[PHImageManager defaultManager] requestImageForAsset:asset
|
||||
targetSize:targetSize
|
||||
contentMode:contentMode
|
||||
options:imageOptions
|
||||
resultHandler:^(UIImage *result, NSDictionary<NSString *, id> *info) {
|
||||
if (result) {
|
||||
|
||||
NSData *imageData = UIImageJPEGRepresentation(result, compression );
|
||||
[imageData writeToFile:destination atomically:YES];
|
||||
resolve(destination);
|
||||
|
||||
} else {
|
||||
NSMutableDictionary* details = [NSMutableDictionary dictionary];
|
||||
[details setValue:info[PHImageErrorKey] forKey:NSLocalizedDescriptionKey];
|
||||
NSError *error = [NSError errorWithDomain:@"RNFS" code:501 userInfo:details];
|
||||
[self reject: reject withError:error];
|
||||
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (NSNumber *)dateToTimeIntervalNumber:(NSDate *)date
|
||||
{
|
||||
return @([date timeIntervalSince1970]);
|
||||
|
|
|
@ -67,7 +67,9 @@ public class Downloader extends AsyncTask<DownloadParams, int[], DownloadResult>
|
|||
statusCode != HttpURLConnection.HTTP_OK &&
|
||||
(
|
||||
statusCode == HttpURLConnection.HTTP_MOVED_PERM ||
|
||||
statusCode == HttpURLConnection.HTTP_MOVED_TEMP
|
||||
statusCode == HttpURLConnection.HTTP_MOVED_TEMP ||
|
||||
statusCode == 307 ||
|
||||
statusCode == 308
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.HashMap;
|
||||
|
@ -87,6 +88,29 @@ public class RNFSManager extends ReactContextBaseJavaModule {
|
|||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void write(String filepath, String base64Content, int position, Promise promise) {
|
||||
try {
|
||||
byte[] bytes = Base64.decode(base64Content, Base64.DEFAULT);
|
||||
|
||||
if (position < 0) {
|
||||
FileOutputStream outputStream = new FileOutputStream(filepath, true);
|
||||
outputStream.write(bytes);
|
||||
outputStream.close();
|
||||
} else {
|
||||
RandomAccessFile file = new RandomAccessFile(filepath, "rw");
|
||||
file.seek(position);
|
||||
file.write(bytes);
|
||||
file.close();
|
||||
}
|
||||
|
||||
promise.resolve(null);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
reject(promise, filepath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void exists(String filepath, Promise promise) {
|
||||
try {
|
||||
|
@ -259,6 +283,7 @@ public class RNFSManager extends ReactContextBaseJavaModule {
|
|||
for (File childFile : files) {
|
||||
WritableMap fileMap = Arguments.createMap();
|
||||
|
||||
fileMap.putInt("mtime", (int)childFile.lastModified());
|
||||
fileMap.putString("name", childFile.getName());
|
||||
fileMap.putString("path", childFile.getAbsolutePath());
|
||||
fileMap.putInt("size", (int)childFile.length());
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"name": "react-native-fs",
|
||||
"version": "v2.1.0-rc.1",
|
||||
"version": "2.3.2",
|
||||
"description": "Native filesystem access for react-native",
|
||||
"main": "FS.common.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"flow": "flow; test $? -eq 0 -o $? -eq 2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:johanneslumpe/react-native-fs.git"
|
||||
"url": "git@github.com:itinance/react-native-fs.git"
|
||||
},
|
||||
"keywords": [
|
||||
"react-component",
|
||||
|
@ -28,7 +29,7 @@
|
|||
"utf8": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"flow-bin": "0.27.0",
|
||||
"flow-bin": "0.28.0",
|
||||
"react": "^15.4.2",
|
||||
"react-native": "^0.40.0"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue