diff --git a/README.md b/README.md index a8a7ae2..ca65331 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,14 @@ const sourceUri = {uri: 'https://foo.com/bar.pdf'}; const destinationPath = "foo-bar/docs/info.pdf"; const mimeType = null; const scope = 'visible'; +const update = false; RNCloudFs.copyToCloud({ sourcePath: sourceUri, targetPath: destinationPath, - mimeType: mimeType, - scope: scope + mimeType, + scope, + update }) .then((path) => { console.log("it worked", path); @@ -76,6 +78,8 @@ _mimeType_: a mime type to store the file with **or null** (android only) , e.g _scope_: a string to specify if the user can access the document (`visible`) or not (`hidden`) +_update_: a boolean to specify if we want to update an existing item instead of creating a new one + ### listFiles (options) Lists files in a directory along with some file metadata. The scope determines if the file listing takes place in the app folder or the public user documents folder. @@ -96,7 +100,6 @@ _targetPath_: a path representing a folder to list files from _scope_: a string to specify if the files are the user-visible documents (`visible`) or the app-visible documents (`hidden`) - ## Android After following the instructions in [Getting started](./docs/getting-started.md) I recommend using [react-native-google-signin](https://github.com/react-native-google-signin/google-signin) to authenticate the user, especially if you need additional scopes besides `auth/drive.file` which is the only scope this package requests, and let that package handle auth. diff --git a/ios/RNCloudFs.m b/ios/RNCloudFs.m index d38ff4e..f4bca69 100644 --- a/ios/RNCloudFs.m +++ b/ios/RNCloudFs.m @@ -13,8 +13,6 @@ @implementation RNCloudFs - - - (dispatch_queue_t)methodQueue { return dispatch_queue_create("RNCloudFs.queue", DISPATCH_QUEUE_SERIAL); @@ -233,13 +231,14 @@ - (dispatch_queue_t)methodQueue RCT_EXPORT_METHOD(copyToCloud:(NSDictionary *)options - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) { // mimeType is ignored for iOS NSDictionary *source = [options objectForKey:@"sourcePath"]; NSString *destinationPath = [options objectForKey:@"targetPath"]; NSString *scope = [options objectForKey:@"scope"]; + BOOL update = [[options objectForKey:@"update"] boolValue]; bool documentsFolder = !scope || [scope caseInsensitiveCompare:@"visible"] == NSOrderedSame; NSFileManager* fileManager = [NSFileManager defaultManager]; @@ -298,7 +297,7 @@ - (dispatch_queue_t)methodQueue return reject(@"error", error.description, nil); } - [self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :resolve :reject]; + [self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :update :resolve :reject]; } else { NSLog(@"source file does not exist %@", sourceUri); return reject(@"error", [NSString stringWithFormat:@"no such file or directory, open '%@'", sourceUri], nil); @@ -311,7 +310,7 @@ - (dispatch_queue_t)methodQueue NSString *filename = [sourceUri lastPathComponent]; NSString *tempFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename]; [urlData writeToFile:tempFile atomically:YES]; - [self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :resolve :reject]; + [self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :update :resolve :reject]; } else { RCTLogTrace(@"source file does not exist %@", sourceUri); return reject(@"error", [NSString stringWithFormat:@"cannot download '%@'", sourceUri], nil); @@ -320,21 +319,22 @@ - (dispatch_queue_t)methodQueue } - (void) moveToICloudDirectory:(bool) documentsFolder :(NSString *)tempFile :(NSString *)destinationPath - :(RCTPromiseResolveBlock)resolver - :(RCTPromiseRejectBlock)rejecter { + :(bool) update + :(RCTPromiseResolveBlock)resolver + :(RCTPromiseRejectBlock)rejecter { if(documentsFolder) { NSURL *ubiquityURL = [self icloudDocumentsDirectory]; - [self moveToICloud:ubiquityURL :tempFile :destinationPath :resolver :rejecter]; + [self moveToICloud:ubiquityURL :tempFile :destinationPath :update :resolver :rejecter]; } else { NSURL *ubiquityURL = [self icloudDirectory]; - [self moveToICloud:ubiquityURL :tempFile :destinationPath :resolver :rejecter]; + [self moveToICloud:ubiquityURL :tempFile :destinationPath :update :resolver :rejecter]; } } -- (void) moveToICloud:(NSURL *)ubiquityURL :(NSString *)tempFile :(NSString *)destinationPath - :(RCTPromiseResolveBlock)resolver - :(RCTPromiseRejectBlock)rejecter { +- (void) moveToICloud:(NSURL *)ubiquityURL :(NSString *)tempFile :(NSString *)destinationPath :(bool) update + :(RCTPromiseResolveBlock)resolver + :(RCTPromiseRejectBlock)rejecter { NSString * destPath = destinationPath; @@ -350,14 +350,16 @@ - (void) moveToICloud:(NSURL *)ubiquityURL :(NSString *)tempFile :(NSString *)de NSURL* targetFile = [ubiquityURL URLByAppendingPathComponent:destPath]; NSURL *dir = [targetFile URLByDeletingLastPathComponent]; + NSString *name = [targetFile lastPathComponent]; NSURL* uniqueFile = targetFile; - if([fileManager fileExistsAtPath:uniqueFile.path]){ - NSError *error; - [fileManager removeItemAtPath:uniqueFile.path error:&error]; - if(error) { - return rejecter(@"error", error.description, nil); + if(!update) { + int count = 1; + while([fileManager fileExistsAtPath:uniqueFile.path]) { + NSString *uniqueName = [NSString stringWithFormat:@"%i.%@", count, name]; + uniqueFile = [dir URLByAppendingPathComponent:uniqueName]; + count++; } } @@ -368,6 +370,12 @@ - (void) moveToICloud:(NSURL *)ubiquityURL :(NSString *)tempFile :(NSString *)de } NSError *error; + + if(update && [fileManager fileExistsAtPath:uniqueFile.path isDirectory:nil]) { + // in update mode, if a icloud file already exists at destination path, we need to delete it to avoid errors + [fileManager removeItemAtPath:uniqueFile.path error:&error]; + } + [fileManager setUbiquitous:YES itemAtURL:[NSURL fileURLWithPath:tempFile] destinationURL:uniqueFile error:&error]; if(error) { return rejecter(@"error", error.description, nil);