From 53211a361f4e9678dd3df1c8b0bdf90ca5af8583 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Tue, 25 Feb 2020 17:19:08 +0100 Subject: [PATCH] feat(Filesystem): add recursive option to writeFile (#2487) --- .../com/getcapacitor/plugin/Filesystem.java | 9 +++++++-- core/src/core-plugin-definitions.ts | 5 +++++ core/src/web/filesystem.ts | 3 ++- electron/src/electron/filesystem.ts | 20 +++++++++++++------ .../Capacitor/Plugins/Filesystem.swift | 9 +++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java index d6e5ab253..5b99f5cb2 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/Filesystem.java @@ -192,6 +192,7 @@ public void writeFile(PluginCall call) { saveCall(call); String path = call.getString("path"); String data = call.getString("data"); + Boolean recursive = call.getBoolean("recursive", false); if (path == null) { Log.e(getLogTag(), "No path or filename retrieved from call"); @@ -215,8 +216,10 @@ public void writeFile(PluginCall call) { if (androidDir.exists() || androidDir.mkdirs()) { // path might include directories as well File fileObject = new File(androidDir, path); - if (fileObject.getParentFile().exists() || fileObject.getParentFile().mkdirs()) { + if (fileObject.getParentFile().exists() || (recursive && fileObject.getParentFile().mkdirs())) { saveFile(call, fileObject, data); + } else { + call.error("Parent folder doesn't exist"); } } else { Log.e(getLogTag(), "Not able to create '" + directory + "'!"); @@ -235,8 +238,10 @@ public void writeFile(PluginCall call) { // do not know where the file is being store so checking the permission to be secure // TODO to prevent permission checking we need a property from the call if (isStoragePermissionGranted(PluginRequestCodes.FILESYSTEM_REQUEST_WRITE_FILE_PERMISSIONS, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - if (fileObject.getParentFile().exists() || fileObject.getParentFile().mkdirs()) { + if (fileObject.getParentFile().exists() || (recursive && fileObject.getParentFile().mkdirs())) { saveFile(call, fileObject, data); + } else { + call.error("Parent folder doesn't exist"); } } } diff --git a/core/src/core-plugin-definitions.ts b/core/src/core-plugin-definitions.ts index 7da5febcc..6ae95be5e 100644 --- a/core/src/core-plugin-definitions.ts +++ b/core/src/core-plugin-definitions.ts @@ -608,6 +608,11 @@ export interface FileWriteOptions { * Pass FilesystemEncoding.UTF8 to write data as string */ encoding?: FilesystemEncoding; + /** + * Whether to create any missing parent directories. + * Defaults to false + */ + recursive?: boolean; } export interface FileAppendOptions { diff --git a/core/src/web/filesystem.ts b/core/src/web/filesystem.ts index 72d9cd346..ff219db16 100644 --- a/core/src/web/filesystem.ts +++ b/core/src/web/filesystem.ts @@ -149,6 +149,7 @@ export class FilesystemPluginWeb extends WebPlugin implements FilesystemPlugin { async writeFile(options: FileWriteOptions): Promise { const path: string = this.getPath(options.directory, options.path); const data = options.data; + const doRecursive = options.recursive; let occupiedEntry = await this.dbRequest('get', [path]) as EntryObj; if (occupiedEntry && occupiedEntry.type === 'directory') @@ -162,7 +163,7 @@ export class FilesystemPluginWeb extends WebPlugin implements FilesystemPlugin { const subDirIndex = parentPath.indexOf('/', 1); if (subDirIndex !== -1) { const parentArgPath = parentPath.substr(subDirIndex); - await this.mkdir({path: parentArgPath, directory: options.directory, recursive: true}); + await this.mkdir({path: parentArgPath, directory: options.directory, recursive: doRecursive}); } } const now = Date.now(); diff --git a/electron/src/electron/filesystem.ts b/electron/src/electron/filesystem.ts index 014b8f748..a51f93ee3 100644 --- a/electron/src/electron/filesystem.ts +++ b/electron/src/electron/filesystem.ts @@ -65,13 +65,21 @@ export class FilesystemPluginElectron extends WebPlugin implements FilesystemPlu const base64Data = options.data.indexOf(',') >= 0 ? options.data.split(',')[1] : options.data; data = Buffer.from(base64Data, 'base64'); } - this.NodeFS.writeFile(lookupPath, data, options.encoding || 'binary', (err: any) => { - if (err) { - reject(err); - return; + const dstDirectory = this.Path.dirname(lookupPath); + this.NodeFS.stat(dstDirectory, (err: any) => { + if(err) { + const doRecursive = options.recursive; + if (doRecursive) { + this.NodeFS.mkdirSync(dstDirectory, {recursive: doRecursive}); + } } - - resolve({uri: lookupPath}); + this.NodeFS.writeFile(lookupPath, data, options.encoding || 'binary', (err: any) => { + if (err) { + reject(err); + return; + } + resolve({uri: lookupPath}); + }); }); }); } diff --git a/ios/Capacitor/Capacitor/Plugins/Filesystem.swift b/ios/Capacitor/Capacitor/Plugins/Filesystem.swift index d8bc56a2d..43105055d 100644 --- a/ios/Capacitor/Capacitor/Plugins/Filesystem.swift +++ b/ios/Capacitor/Capacitor/Plugins/Filesystem.swift @@ -85,6 +85,7 @@ public class CAPFilesystemPlugin : CAPPlugin { */ @objc func writeFile(_ call: CAPPluginCall) { let encoding = call.getString("encoding") + let recursive = call.get("recursive", Bool.self, false)! // TODO: Allow them to switch encoding guard let file = call.get("path", String.self) else { handleError(call, "path must be provided and must be a string.") @@ -104,6 +105,14 @@ public class CAPFilesystemPlugin : CAPPlugin { } do { + if !FileManager.default.fileExists(atPath: fileUrl.deletingLastPathComponent().absoluteString) { + if recursive { + try FileManager.default.createDirectory(at: fileUrl.deletingLastPathComponent(), withIntermediateDirectories: recursive, attributes: nil) + } else { + handleError(call, "Parent folder doesn't exist"); + return + } + } if encoding != nil { try data.write(to: fileUrl, atomically: false, encoding: .utf8) } else {