From c6ec354f2df2ccd72c07ef4cea11afa78ddbc0f7 Mon Sep 17 00:00:00 2001 From: Sebastian Makinson Date: Fri, 3 Nov 2017 08:36:20 -0600 Subject: [PATCH] Added rejection and errors for copyAssetsVideoIOS --- README.md | 14 ++++---- RNFSManager.m | 91 +++++++++++++++++++++++++++------------------------ 2 files changed, 55 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 3e4465f..3328684 100644 --- a/README.md +++ b/README.md @@ -359,8 +359,8 @@ The returned promise resolves with an array of objects with the following proper type ReadDirItem = { name: string; // The name of the item path: string; // The absolute path to the item - size: string; // Size in bytes. - // Note that the size of files compressed during the creation of the APK (such as JSON files) cannot be determined. + size: string; // Size in bytes. + // Note that the size of files compressed during the creation of the APK (such as JSON files) cannot be determined. // `size` will be set to -1 in this case. isFile: () => boolean; // Is the file just a file? isDirectory: () => boolean; // Is the file a directory? @@ -442,7 +442,7 @@ Note: Android only. Will overwrite destPath if it already exists iOS-only: 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 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. @@ -456,7 +456,7 @@ To copy a video from assets-library and save it as a mp4-file, refer to copyAsse 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. -### copyAssetsVideoIOS(videoUri: string, destPath: string) +### copyAssetsVideoIOS(videoUri: string, destPath: string): Promise iOS-only: copies a video from assets-library, that is prefixed with 'assets-library://asset/asset.MOV?...' to a specific destination. @@ -481,7 +481,7 @@ Reads the file at `path` and returns its checksum as determined by `algorithm`, ### `touch(filepath: string, mtime?: Date, ctime?: Date): Promise` -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`. +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` @@ -635,12 +635,12 @@ type FSInfoResult = { `groupIdentifier` (`string`) Any value from the *com.apple.security.application-groups* entitlements list. -Returns the absolute path to the directory shared for all applications with the same security group identifier. +Returns the absolute path to the directory shared for all applications with the same security group identifier. This directory can be used to to share files between application of the same developer. Invalid group identifier will cause a rejection. -For more information read the [Adding an App to an App Group](https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19) section. +For more information read the [Adding an App to an App Group](https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19) section. ## Test / Demo app diff --git a/RNFSManager.m b/RNFSManager.m index 40c43e3..613082f 100755 --- a/RNFSManager.m +++ b/RNFSManager.m @@ -159,30 +159,30 @@ RCT_EXPORT_METHOD(write:(NSString *)filepath 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); @@ -273,41 +273,41 @@ RCT_EXPORT_METHOD(read:(NSString *)filepath 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); } @@ -619,17 +619,17 @@ 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. - * + * JPEG-Images. + * * Video-Support: - * + * * One can use this method also to create a thumbNail from a video. * Currently it is impossible to specify a concrete position, the OS will decide wich * Thumbnail you'll get then. * To copy a video from assets-library and save it as a mp4-file, use the method * copyAssetsVideoIOS. - * - * It is also supported to scale the image via scale-factor (0.0-1.0) or with a specific + * + * 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 @@ -644,31 +644,31 @@ RCT_EXPORT_METHOD(copyAssetsFileIOS: (NSString *) imageUri { 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) { @@ -678,12 +678,12 @@ RCT_EXPORT_METHOD(copyAssetsFileIOS: (NSString *) imageUri 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 @@ -691,49 +691,48 @@ RCT_EXPORT_METHOD(copyAssetsFileIOS: (NSString *) imageUri options:imageOptions resultHandler:^(UIImage *result, NSDictionary *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]; - + } }]; } /** * iOS Only: copy videos from the assets-library (camera-roll) to a specific path as mp4-file. - * + * * To create a thumbnail from the video, refer to copyAssetsFileIOS */ RCT_EXPORT_METHOD(copyAssetsVideoIOS: (NSString *) imageUri atFilepath: (NSString *) destination resolver: (RCTPromiseResolveBlock) resolve rejecter: (RCTPromiseRejectBlock) reject) - { NSURL* url = [NSURL URLWithString:imageUri]; __block NSURL* videoURL = [NSURL URLWithString:destination]; - + __block NSError *error = nil; PHFetchResult *phAssetFetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil]; PHAsset *phAsset = [phAssetFetchResult firstObject]; dispatch_group_t group = dispatch_group_create(); dispatch_group_enter(group); - + [[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) { - + if ([asset isKindOfClass:[AVURLAsset class]]) { NSURL *url = [(AVURLAsset *)asset URL]; NSLog(@"Final URL %@",url); NSData *videoData = [NSData dataWithContentsOfURL:url]; - - BOOL writeResult = [videoData writeToFile:destination atomically:true]; - + + BOOL writeResult = [videoData writeToFile:destination options:NSDataWritingAtomic error:&error]; + if(writeResult) { NSLog(@"video success"); } @@ -744,7 +743,13 @@ RCT_EXPORT_METHOD(copyAssetsVideoIOS: (NSString *) imageUri } }]; dispatch_group_wait(group, DISPATCH_TIME_FOREVER); - resolve(destination); + + if (error) { + NSLog(@"RNFS: %@", error); + return [self reject:reject withError:error]; + } + + return resolve(destination); } RCT_EXPORT_METHOD(touch:(NSString*)filepath