react-native-fs/RNFSManager.m

433 lines
15 KiB
Mathematica
Raw Normal View History

2015-05-08 17:05:37 +00:00
//
// RNFSManager.m
// RNFSManager
//
// Created by Johannes Lumpe on 08/05/15.
// Copyright (c) 2015 Johannes Lumpe. All rights reserved.
//
#import "RNFSManager.h"
#import "RCTBridge.h"
#import "NSArray+Map.h"
#import "Downloader.h"
2016-05-30 22:13:50 +00:00
#import "Uploader.h"
2015-11-20 00:16:13 +00:00
#import "RCTEventDispatcher.h"
2015-05-08 17:05:37 +00:00
@interface RNFSManager()
@property (retain) NSMutableDictionary* downloaders;
2016-05-30 22:13:50 +00:00
@property (retain) NSMutableDictionary* uploaders;
@end
2015-05-08 17:05:37 +00:00
@implementation RNFSManager
2015-11-20 00:16:13 +00:00
@synthesize bridge = _bridge;
2015-05-08 17:05:37 +00:00
RCT_EXPORT_MODULE();
- (dispatch_queue_t)methodQueue
{
return dispatch_queue_create("pe.lum.rnfs", DISPATCH_QUEUE_SERIAL);
}
2015-05-08 17:05:37 +00:00
RCT_EXPORT_METHOD(readDir:(NSString *)dirPath
callback:(RCTResponseSenderBlock)callback)
{
2015-05-08 17:05:37 +00:00
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
2015-05-08 17:05:37 +00:00
NSArray *contents = [fileManager contentsOfDirectoryAtPath:dirPath error:&error];
contents = [contents rnfs_mapObjectsUsingBlock:^id(NSString *obj, NSUInteger idx) {
2015-10-20 22:31:29 +00:00
NSString *path = [dirPath stringByAppendingPathComponent:obj];
NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:nil];
2015-05-08 17:05:37 +00:00
return @{
2016-06-29 23:08:53 +00:00
@"name": obj,
@"path": path,
@"size": [attributes objectForKey:NSFileSize],
@"type": [attributes objectForKey:NSFileType]
};
2015-05-08 17:05:37 +00:00
}];
2015-05-08 17:05:37 +00:00
if (error) {
return callback([self makeErrorPayload:error]);
}
2015-05-08 17:05:37 +00:00
callback(@[[NSNull null], contents]);
}
2016-01-28 18:20:02 +00:00
RCT_EXPORT_METHOD(exists:(NSString *)filepath
2016-01-28 13:36:31 +00:00
callback:(RCTResponseSenderBlock)callback)
{
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filepath];
callback(@[[NSNull null], [NSNumber numberWithBool:fileExists]]);
}
RCT_EXPORT_METHOD(stat:(NSString *)filepath
callback:(RCTResponseSenderBlock)callback)
{
NSError *error = nil;
2015-05-08 17:05:37 +00:00
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:&error];
2015-05-08 17:05:37 +00:00
if (error) {
return callback([self makeErrorPayload:error]);
}
2015-05-08 17:05:37 +00:00
attributes = @{
2016-06-29 23:08:53 +00:00
@"ctime": [self dateToTimeIntervalNumber:(NSDate *)[attributes objectForKey:NSFileCreationDate]],
@"mtime": [self dateToTimeIntervalNumber:(NSDate *)[attributes objectForKey:NSFileModificationDate]],
@"size": [attributes objectForKey:NSFileSize],
@"type": [attributes objectForKey:NSFileType],
@"mode": @([[NSString stringWithFormat:@"%ld", (long)[(NSNumber *)[attributes objectForKey:NSFilePosixPermissions] integerValue]] integerValue])
};
2015-05-08 17:05:37 +00:00
callback(@[[NSNull null], attributes]);
}
RCT_EXPORT_METHOD(writeFile:(NSString *)filepath
contents:(NSString *)base64Content
attributes:(NSDictionary *)attributes
callback:(RCTResponseSenderBlock)callback)
{
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters];
2016-06-29 23:08:53 +00:00
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:attributes];
if (!success) {
return callback(@[[NSString stringWithFormat:@"Could not write file at path %@", filepath]]);
}
2016-06-29 23:08:53 +00:00
return callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]);
}
RCT_EXPORT_METHOD(appendFile:(NSString *)filepath
contents:(NSString *)base64Content
attributes:(NSDictionary *)attributes
callback:(RCTResponseSenderBlock)callback)
{
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSFileManager *fM = [NSFileManager defaultManager];
if (![fM fileExistsAtPath:filepath])
{
2016-06-29 23:08:53 +00:00
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:attributes];
if (!success) {
return callback(@[[NSString stringWithFormat:@"Could not write file at path %@", filepath]]);
} else {
return callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]);
}
2016-06-29 23:08:53 +00:00
}
@try {
NSFileHandle *fH = [NSFileHandle fileHandleForUpdatingAtPath:filepath];
2016-06-29 23:08:53 +00:00
[fH seekToEndOfFile];
[fH writeData:data];
2016-06-29 23:08:53 +00:00
return callback(@[[NSNull null], [NSNumber numberWithBool:true], filepath]);
} @catch (NSException *e) {
return callback([self makeErrorPayload:e]);
}
}
RCT_EXPORT_METHOD(unlink:(NSString*)filepath
callback:(RCTResponseSenderBlock)callback)
{
2015-05-08 21:17:10 +00:00
NSFileManager *manager = [NSFileManager defaultManager];
BOOL exists = [manager fileExistsAtPath:filepath isDirectory:false];
if (!exists) {
return callback(@[[NSString stringWithFormat:@"File at path %@ does not exist", filepath]]);
}
NSError *error = nil;
2015-05-08 21:17:10 +00:00
BOOL success = [manager removeItemAtPath:filepath error:&error];
if (!success) {
return callback([self makeErrorPayload:error]);
}
callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]);
}
2015-10-20 22:31:29 +00:00
RCT_EXPORT_METHOD(mkdir:(NSString*)filepath
excludeFromBackup:(BOOL)excludeFromBackup
2015-10-20 22:31:29 +00:00
callback:(RCTResponseSenderBlock)callback)
{
NSFileManager *manager = [NSFileManager defaultManager];
NSError *error = nil;
BOOL success = [manager createDirectoryAtPath:filepath withIntermediateDirectories:YES attributes:nil error:&error];
if (!success) {
return callback([self makeErrorPayload:error]);
}
NSURL *url = [NSURL fileURLWithPath:filepath];
success = [url setResourceValue: [NSNumber numberWithBool: excludeFromBackup] forKey: NSURLIsExcludedFromBackupKey error: &error];
if (!success) {
return callback([self makeErrorPayload:error]);
}
2015-10-20 22:31:29 +00:00
callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]);
}
RCT_EXPORT_METHOD(readFile:(NSString *)filepath
callback:(RCTResponseSenderBlock)callback)
{
2015-05-08 17:05:37 +00:00
NSData *content = [[NSFileManager defaultManager] contentsAtPath:filepath];
NSString *base64Content = [content base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
2015-05-08 21:17:10 +00:00
2015-05-08 17:05:37 +00:00
if (!base64Content) {
return callback(@[[NSString stringWithFormat:@"Could not read file at path %@", filepath]]);
}
2015-05-08 17:05:37 +00:00
callback(@[[NSNull null], base64Content]);
}
2016-01-16 18:52:56 +00:00
RCT_EXPORT_METHOD(moveFile:(NSString *)filepath
2016-01-27 16:52:56 +00:00
destPath:(NSString *)destPath
2016-01-16 18:52:56 +00:00
callback:(RCTResponseSenderBlock)callback)
{
2016-06-29 23:08:53 +00:00
NSFileManager *manager = [NSFileManager defaultManager];
2016-04-07 19:29:36 +00:00
2016-06-29 23:08:53 +00:00
NSError *error = nil;
BOOL success = [manager moveItemAtPath:filepath toPath:destPath error:&error];
2016-04-07 19:29:36 +00:00
2016-06-29 23:08:53 +00:00
if (!success) {
return callback([self makeErrorPayload:error]);
}
2016-04-07 19:29:36 +00:00
2016-06-29 23:08:53 +00:00
callback(@[[NSNull null], [NSNumber numberWithBool:success], destPath]);
2016-01-16 18:52:56 +00:00
}
2016-07-03 10:10:24 +00:00
RCT_EXPORT_METHOD(copyFile:(NSString *)filepath
destPath:(NSString *)destPath
callback:(RCTResponseSenderBlock)callback)
{
NSFileManager *manager = [NSFileManager defaultManager];
NSError *error = nil;
BOOL success = [manager copyItemAtPath:filepath toPath:destPath error:&error];
if (!success) {
return callback([self makeErrorPayload:error]);
}
callback(@[[NSNull null], [NSNumber numberWithBool:success], destPath]);
}
RCT_EXPORT_METHOD(downloadFile:(NSDictionary *)options
2015-10-20 23:17:03 +00:00
callback:(RCTResponseSenderBlock)callback)
{
DownloadParams* params = [DownloadParams alloc];
2016-04-07 19:29:36 +00:00
NSNumber* jobId = options[@"jobId"];
params.fromUrl = options[@"fromUrl"];
params.toFile = options[@"toFile"];
NSDictionary* headers = options[@"headers"];
params.headers = headers;
NSNumber* background = options[@"background"];
params.background = [background boolValue];
NSNumber* progressDivider = options[@"progressDivider"];
2016-05-31 09:46:03 +00:00
params.progressDivider = progressDivider;
2016-05-30 22:13:50 +00:00
params.completeCallback = ^(NSNumber* statusCode, NSNumber* bytesWritten) {
NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithDictionary: @{@"jobId": jobId,
2016-06-29 23:08:53 +00:00
@"statusCode": statusCode}];
if (bytesWritten) {
[result setObject:bytesWritten forKey: @"bytesWritten"];
}
return callback(@[[NSNull null], result]);
};
2015-10-22 23:13:12 +00:00
2015-11-23 17:08:52 +00:00
params.errorCallback = ^(NSError* error) {
2015-10-22 23:13:12 +00:00
return callback([self makeErrorPayload:error]);
};
2016-04-07 19:29:36 +00:00
params.beginCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSDictionary* headers) {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadBegin-%@", jobId]
body:@{@"jobId": jobId,
@"statusCode": statusCode,
2015-11-20 00:16:13 +00:00
@"contentLength": contentLength,
@"headers": headers}];
};
2016-04-07 19:29:36 +00:00
params.progressCallback = ^(NSNumber* contentLength, NSNumber* bytesWritten) {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"DownloadProgress-%@", jobId]
2016-04-07 19:29:36 +00:00
body:@{@"jobId": jobId,
@"contentLength": contentLength,
2015-11-20 00:16:13 +00:00
@"bytesWritten": bytesWritten}];
};
2015-10-20 23:17:03 +00:00
2015-11-23 17:08:52 +00:00
if (!self.downloaders) self.downloaders = [[NSMutableDictionary alloc] init];
2016-04-07 19:29:36 +00:00
Downloader* downloader = [Downloader alloc];
[downloader downloadFile:params];
2016-04-07 19:29:36 +00:00
[self.downloaders setValue:downloader forKey:[jobId stringValue]];
}
2015-11-23 17:08:52 +00:00
RCT_EXPORT_METHOD(stopDownload:(nonnull NSNumber *)jobId)
{
Downloader* downloader = [self.downloaders objectForKey:[jobId stringValue]];
2016-04-07 19:29:36 +00:00
if (downloader != nil) {
[downloader stopDownload];
}
2015-10-20 23:17:03 +00:00
}
2016-05-30 22:13:50 +00:00
RCT_EXPORT_METHOD(uploadFiles:(NSDictionary *)options
callback:(RCTResponseSenderBlock)callback)
{
UploadParams* params = [UploadParams alloc];
NSNumber* jobId = options[@"jobId"];
params.toUrl = options[@"toUrl"];
params.files = options[@"files"];
NSDictionary* headers = options[@"headers"];
NSDictionary* fields = options[@"fields"];
NSString* method = options[@"method"];
params.headers = headers;
params.fields = fields;
params.method = method;
params.completeCallback = ^(NSString* body, NSURLResponse *resp) {
2016-06-15 10:33:35 +00:00
2016-05-30 22:13:50 +00:00
NSMutableDictionary* result = [[NSMutableDictionary alloc] initWithDictionary: @{@"jobId": jobId,
@"body": body,
2016-06-15 10:33:35 +00:00
@"response": body}];
if ([resp isKindOfClass:[NSHTTPURLResponse class]]) {
[result setValue:((NSHTTPURLResponse *)resp).allHeaderFields forKey:@"headers"];
[result setValue:[NSNumber numberWithUnsignedInteger:((NSHTTPURLResponse *)resp).statusCode] forKey:@"statusCode"];
}
2016-05-30 22:13:50 +00:00
return callback(@[[NSNull null], result]);
};
params.errorCallback = ^(NSError* error) {
return callback([self makeErrorPayload:error]);
};
params.beginCallback = ^() {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"UploadBegin-%@", jobId]
body:@{@"jobId": jobId}];
};
params.progressCallback = ^(NSNumber* totalBytesExpectedToSend, NSNumber* totalBytesSent) {
[self.bridge.eventDispatcher sendAppEventWithName:[NSString stringWithFormat:@"UploadProgress-%@", jobId]
2016-06-29 23:08:53 +00:00
body:@{@"jobId": jobId,
@"totalBytesExpectedToSend": totalBytesExpectedToSend,
2016-05-30 22:13:50 +00:00
@"totalBytesSent": totalBytesSent}];
};
if (!self.uploaders) self.uploaders = [[NSMutableDictionary alloc] init];
Uploader* uploader = [Uploader alloc];
[uploader uploadFiles:params];
[self.uploaders setValue:uploader forKey:[jobId stringValue]];
}
RCT_EXPORT_METHOD(stopUpload:(nonnull NSNumber *)jobId)
{
Uploader* uploader = [self.uploaders objectForKey:[jobId stringValue]];
if (uploader != nil) {
[uploader stopUpload];
}
}
RCT_EXPORT_METHOD(pathForBundle:(NSString *)bundleNamed
callback:(RCTResponseSenderBlock)callback)
{
2016-06-29 23:08:53 +00:00
NSString *path = [[NSBundle mainBundle].bundlePath stringByAppendingFormat:@"/%@.bundle", bundleNamed];
NSBundle *bundle = [NSBundle bundleWithPath:path];
2016-06-29 23:08:53 +00:00
if (!bundle) {
bundle = [NSBundle bundleForClass:NSClassFromString(bundleNamed)];
path = bundle.bundlePath;
}
2015-10-20 22:31:29 +00:00
2016-06-29 23:08:53 +00:00
if (!bundle.isLoaded) {
[bundle load];
}
2016-06-29 23:08:53 +00:00
if (path) {
callback(@[[NSNull null], path]);
} else {
callback(@[[NSError errorWithDomain:NSPOSIXErrorDomain
code:NSFileNoSuchFileError
userInfo:nil].localizedDescription,
[NSNull null]]);
}
}
2016-03-18 17:53:00 +00:00
RCT_EXPORT_METHOD(getFSInfo:(RCTResponseSenderBlock)callback)
{
2016-06-29 23:08:53 +00:00
unsigned long long totalSpace = 0;
unsigned long long totalFreeSpace = 0;
__autoreleasing NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
if (dictionary) {
NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
callback(@[[NSNull null],
@{
@"totalSpace": [NSNumber numberWithUnsignedLongLong:totalSpace],
@"freeSpace": [NSNumber numberWithUnsignedLongLong:totalFreeSpace]
}
]);
} else {
callback(@[error, [NSNull null]]);
}
2016-03-18 17:53:00 +00:00
}
- (NSNumber *)dateToTimeIntervalNumber:(NSDate *)date
{
return @([date timeIntervalSince1970]);
2015-05-08 17:05:37 +00:00
}
- (NSArray *)makeErrorPayload:(NSError *)error
{
2015-05-08 17:05:37 +00:00
return @[@{
2016-06-29 23:08:53 +00:00
@"description": error.localizedDescription,
@"code": @(error.code)
}];
2015-05-08 17:05:37 +00:00
}
- (NSString *)getPathForDirectory:(int)directory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES);
return [paths firstObject];
}
2015-05-08 17:05:37 +00:00
- (NSDictionary *)constantsToExport
{
return @{
2016-06-29 23:08:53 +00:00
@"MainBundlePath": [[NSBundle mainBundle] bundlePath],
@"NSCachesDirectoryPath": [self getPathForDirectory:NSCachesDirectory],
@"NSDocumentDirectoryPath": [self getPathForDirectory:NSDocumentDirectory],
@"NSExternalDirectoryPath": [NSNull null],
@"NSTemporaryDirectoryPath": NSTemporaryDirectory(),
@"NSLibraryDirectoryPath": [self getPathForDirectory:NSLibraryDirectory],
@"NSFileTypeRegular": NSFileTypeRegular,
@"NSFileTypeDirectory": NSFileTypeDirectory
};
2015-05-08 17:05:37 +00:00
}
@end