From 5c3613f3385b02e40135992b50240db18146dabe Mon Sep 17 00:00:00 2001 From: Alexandre Papin Date: Fri, 18 Mar 2016 23:27:20 +0100 Subject: [PATCH 1/2] Add wrapper for file plugin with some methods --- src/index.ts | 6 +- src/plugins/file.ts | 342 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 334 insertions(+), 14 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8ad5c793a..3c14e5159 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,7 +25,7 @@ import {DeviceMotion} from './plugins/devicemotion'; import {DeviceOrientation} from './plugins/deviceorientation'; import {Dialogs} from './plugins/dialogs'; import {Facebook} from './plugins/facebook'; -//import {File} from './plugins/file'; +import {File} from './plugins/file'; import {Flashlight} from './plugins/flashlight'; import {Geolocation} from './plugins/geolocation'; import {Globalization} from './plugins/globalization'; @@ -63,7 +63,7 @@ export { DeviceOrientation, Dialogs, Facebook, - //File, + File, Flashlight, Geolocation, Globalization, @@ -105,7 +105,7 @@ window['IonicNative'] = { DeviceOrientation: DeviceOrientation, Dialogs: Dialogs, Facebook: Facebook, - //File: File, + File: File, Flashlight: Flashlight, Geolocation: Geolocation, Globalization: Globalization, diff --git a/src/plugins/file.ts b/src/plugins/file.ts index 6ce26dacc..66d077187 100644 --- a/src/plugins/file.ts +++ b/src/plugins/file.ts @@ -1,11 +1,331 @@ -// import {Plugin, Cordova} from './plugin'; -// -// declare var window; -// -// @Plugin({ -// name: 'File', -// plugin: 'cordova-plugin-file', -// pluginRef: 'cordova.file' -// }) -// export class File { -// } +import {Plugin, Cordova} from './plugin'; + +declare var window; + +/** + * @name File + * @description + * This plugin implements a File API allowing read/write access to files residing on the device. + * + * This plugin is based on several specs, including : The HTML5 File API http://www.w3.org/TR/FileAPI/ + * The (now-defunct) Directories and System extensions Latest: http://www.w3.org/TR/2012/WD-file-system-api-20120417/ + * Although most of the plugin code was written when an earlier spec was current: http://www.w3.org/TR/2011/WD-file-system-api-20110419/ + * It also implements the FileWriter spec : http://dev.w3.org/2009/dap/file-system/file-writer.html + * + * @usage + * + * ```ts + * File.removeRecursively(file.applicationStorageDirectory, + * "tmp").then(result => {}, err => {}); + * ``` + */ +@Plugin({ + plugin: 'cordova-plugin-file', + pluginRef: 'cordova.file', + repo: 'https://github.com/apache/cordova-plugin-file' +}) +export class File { + static cordovaFileError: {} = { + 1: 'NOT_FOUND_ERR', + 2: 'SECURITY_ERR', + 3: 'ABORT_ERR', + 4: 'NOT_READABLE_ERR', + 5: 'ENCODING_ERR', + 6: 'NO_MODIFICATION_ALLOWED_ERR', + 7: 'INVALID_STATE_ERR', + 8: 'SYNTAX_ERR', + 9: 'INVALID_MODIFICATION_ERR', + 10: 'QUOTA_EXCEEDED_ERR', + 11: 'TYPE_MISMATCH_ERR', + 12: 'PATH_EXISTS_ERR' + }; + + // @Cordova() + // static getFreeDiskSpace(): Promise { return } + + static checkDir(path: string, dir: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(dir))) { + rejectFn('directory cannot start with \/'); + } + + try { + var directory = path + dir; + + window.resolveLocalFileSystemURL(directory, function (fileSystem) { + if (fileSystem.isDirectory === true) { + resolveFn(fileSystem); + } else { + rejectFn({code: 13, message: 'input is not a directory'}); + } + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + } catch (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + } + + return promise; + } + + static createDir(path: string, dirName: string, replace: boolean): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(dirName))) { + rejectFn('directory cannot start with \/'); + } + + replace = replace ? false : true; + + var options = { + create: true, + exclusive: replace + }; + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getDirectory(dirName, options, function (result) { + resolveFn(result); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + static removeDir(path: string, dirName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(dirName))) { + rejectFn('directory cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getDirectory(dirName, {create: false}, function (dirEntry) { + dirEntry.remove(function () { + resolveFn({success: true, fileRemoved: dirEntry}); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + }, function (er) { + er.message = File.cordovaFileError[er.code]; + rejectFn(er); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + // static moveDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { return } + + // static copyDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { return } + + static listDir(path: string, dirName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(dirName))) { + rejectFn('directory cannot start with \/'); + } + + var options = { + create: false, + exclusive: false + }; + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getDirectory(dirName, options, function (parent) { + var reader = parent.createReader(); + reader.readEntries(function (entries) { + resolveFn(entries); + }, function () { + rejectFn('DIR_READ_ERROR : ' + path + dirName); + }); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + static removeRecursively(path: string, dirName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(dirName))) { + rejectFn('directory cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getDirectory(dirName, {create: false}, function (dirEntry) { + dirEntry.removeRecursively(function () { + resolveFn({success: true, fileRemoved: dirEntry}); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + }, function (er) { + er.message = File.cordovaFileError[er.code]; + rejectFn(er); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + static checkFile(path: string, file: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(file))) { + rejectFn('file cannot start with \/'); + } + + try { + var directory = path + file; + + window.resolveLocalFileSystemURL(directory, function (fileSystem) { + if (fileSystem.isFile === true) { + resolveFn(fileSystem); + } else { + rejectFn({code: 13, message: 'input is not a file'}); + } + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + } catch (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + } + + return promise; + } + + static createFile(path: string, fileName: string, replace: boolean): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + + if ((/^\//.test(fileName))) { + rejectFn('file-name cannot start with \/'); + } + + replace = replace ? false : true; + + var options = { + create: true, + exclusive: replace + }; + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getFile(fileName, options, function (result) { + resolveFn(result); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + static removeFile(path: string, fileName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + if ((/^\//.test(fileName))) { + rejectFn('file-name cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getFile(fileName, {create: false}, function (fileEntry) { + fileEntry.remove(function () { + resolveFn({success: true, fileRemoved: fileEntry}); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + }, function (er) { + er.message = File.cordovaFileError[er.code]; + rejectFn(er); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + // static writeFile(path: string, fileName: string, text: string, replace: boolean): Promise { return } + + // static writeExistingFile(path: string, fileName: string, text: string): Promise { return } + + // static readAsText(path: string, file: string): Promise { return } + + // static readAsDataURL(path: string, file: string): Promise { return } + + // static readAsBinaryString(path: string, file: string): Promise { return } + + // static readAsArrayBuffer(path: string, file: string): Promise { return } + + // static moveFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { return } + + // static copyFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { return } +} From da1facab70384e9d37d677b952b0c106d3f4a25b Mon Sep 17 00:00:00 2001 From: Alexandre Papin Date: Mon, 21 Mar 2016 13:19:27 +0100 Subject: [PATCH 2/2] Add a few more methods and add documentation --- src/plugins/file.ts | 257 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 246 insertions(+), 11 deletions(-) diff --git a/src/plugins/file.ts b/src/plugins/file.ts index 66d077187..54874bcbe 100644 --- a/src/plugins/file.ts +++ b/src/plugins/file.ts @@ -11,13 +11,6 @@ declare var window; * The (now-defunct) Directories and System extensions Latest: http://www.w3.org/TR/2012/WD-file-system-api-20120417/ * Although most of the plugin code was written when an earlier spec was current: http://www.w3.org/TR/2011/WD-file-system-api-20110419/ * It also implements the FileWriter spec : http://dev.w3.org/2009/dap/file-system/file-writer.html - * - * @usage - * - * ```ts - * File.removeRecursively(file.applicationStorageDirectory, - * "tmp").then(result => {}, err => {}); - * ``` */ @Plugin({ plugin: 'cordova-plugin-file', @@ -43,6 +36,13 @@ export class File { // @Cordova() // static getFreeDiskSpace(): Promise { return } + /** + * Check if a directory exists in a certain path, directory. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} dir Name of directory to check + * @return Returns a Promise that resolves or rejects with an error. + */ static checkDir(path: string, dir: string): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -72,6 +72,16 @@ export class File { return promise; } + /** + * Creates a new directory in the specific path. + * The replace boolean value determines whether to replace an existing directory with the same name. + * If an existing directory exists and the replace value is false, the promise will fail and return an error. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} dirName Name of directory to create + * @param {boolean} replace If true, replaces file with same name. If false returns error + * @return Returns a Promise that resolves or rejects with an error. + */ static createDir(path: string, dirName: string, replace: boolean): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -107,6 +117,13 @@ export class File { return promise; } + /** + * Remove a directory at a given path + * + * @param {string} path The path to the directory + * @param {string} dirName The directory name + * @return Returns a Promise that resolves or rejects with an error. + */ static removeDir(path: string, dirName: string): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -140,10 +157,107 @@ export class File { return promise; } - // static moveDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { return } + /** + * Move a directory to a given path + * + * @param {string} path The source path to the directory + * @param {string} dirName The source directory name + * @param {string} newPath The destionation path to the directory + * @param {string} newDirName The destination directory name + * @return Returns a Promise that resolves or rejects with an error. + */ + static moveDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) - // static copyDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { return } + newDirName = newDirName || dirName; + if ((/^\//.test(newDirName))) { + rejectFn('directory cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getDirectory(dirName, {create: false}, function (dirEntry) { + window.resolveLocalFileSystemURL(newPath, function (newDirEntry) { + dirEntry.moveTo(newDirEntry, newDirName, function (result) { + resolveFn(result); + }, function (error) { + rejectFn(error); + }); + }, function (erro) { + rejectFn(erro); + }); + }, function (err) { + rejectFn(err); + }); + }, function (er) { + rejectFn(er); + }); + } catch (e) { + rejectFn(e); + } + + return promise; + } + + /** + * Copy a directory in various methods. If destination directory exists, will fail to copy. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} dirName Name of directory to copy + * @param {string} newPath Base FileSystem of new location + * @param {string} newDirName New name of directory to copy to (leave blank to remain the same) + * @return Returns a Promise that resolves or rejects with an error. + */ + static copyDir(path: string, dirName: string, newPath: string, newDirName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + newDirName = newDirName || dirName; + + if ((/^\//.test(newDirName))) { + rejectFn('directory cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getDirectory(dirName, {create: false, exclusive: false}, function (dirEntry) { + + window.resolveLocalFileSystemURL(newPath, function (newDirEntry) { + dirEntry.copyTo(newDirEntry, newDirName, function (result) { + resolveFn(result); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (erro) { + erro.message = File.cordovaFileError[erro.code]; + rejectFn(erro); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + }, function (er) { + er.message = File.cordovaFileError[er.code]; + rejectFn(er); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } + + /** + * List files and directory from a given path + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} dirName Name of directory + * @return Returns a Promise that resolves or rejects with an error. + */ static listDir(path: string, dirName: string): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -182,6 +296,13 @@ export class File { return promise; } + /** + * Removes all files and the directory from a desired location. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} dirName Name of directory + * @return Returns a Promise that resolves or rejects with an error. + */ static removeRecursively(path: string, dirName: string): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -215,6 +336,13 @@ export class File { return promise; } + /** + * Check if a file exists in a certain path, directory. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} file Name of file to check + * @return Returns a Promise that resolves or rejects with an error. + */ static checkFile(path: string, file: string): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -244,6 +372,16 @@ export class File { return promise; } + /** + * Creates a new file in the specific path. + * The replace boolean value determines whether to replace an existing file with the same name. + * If an existing file exists and the replace value is false, the promise will fail and return an error. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} fileName Name of file to create + * @param {boolean} replace If true, replaces file with same name. If false returns error + * @return Returns a Promise that resolves or rejects with an error. + */ static createFile(path: string, fileName: string, replace: boolean): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -280,6 +418,13 @@ export class File { return promise; } + /** + * Removes a file from a desired location. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} fileName Name of file to remove + * @return Returns a Promise that resolves or rejects with an error. + */ static removeFile(path: string, fileName: string): Promise { let resolveFn, rejectFn; let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) @@ -325,7 +470,97 @@ export class File { // static readAsArrayBuffer(path: string, file: string): Promise { return } - // static moveFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { return } + /** + * Move a file to a given path. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} fileName Name of file to move + * @param {string} newPath Base FileSystem of new location + * @param {string} newFileName New name of file to move to (leave blank to remain the same) + * @return Returns a Promise that resolves or rejects with an error. + */ + static moveFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) - // static copyFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { return } + newFileName = newFileName || fileName + + if ((/^\//.test(newFileName))) { + rejectFn('file-name cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getFile(fileName, {create: false}, function (fileEntry) { + window.resolveLocalFileSystemURL(newPath, function (newFileEntry) { + fileEntry.moveTo(newFileEntry, newFileName, function (result) { + resolveFn(result); + }, function (error) { + rejectFn(error); + }); + }, function (err) { + rejectFn(err); + }); + }, function (err) { + rejectFn(err); + }); + }, function (er) { + rejectFn(er); + }); + } catch (e) { + rejectFn(e); + } + + return promise; + } + + /** + * Copy a file in various methods. If file exists, will fail to copy. + * + * @param {string} path Base FileSystem. Please refer to the iOS and Android filesystems above + * @param {string} fileName Name of file to copy + * @param {string} newPath Base FileSystem of new location + * @param {string} newFileName New name of file to copy to (leave blank to remain the same) + * @return Returns a Promise that resolves or rejects with an error. + */ + static copyFile(path: string, fileName: string, newPath: string, newFileName: string): Promise { + let resolveFn, rejectFn; + let promise = new Promise((resolve, reject) => {resolveFn = resolve; rejectFn = reject; }) + + newFileName = newFileName || fileName + + if ((/^\//.test(newFileName))) { + rejectFn('file-name cannot start with \/'); + } + + try { + window.resolveLocalFileSystemURL(path, function (fileSystem) { + fileSystem.getFile(fileName, {create: false, exclusive: false}, function (fileEntry) { + + window.resolveLocalFileSystemURL(newPath, function (newFileEntry) { + fileEntry.copyTo(newFileEntry, newFileName, function (result) { + resolveFn(result); + }, function (error) { + error.message = File.cordovaFileError[error.code]; + rejectFn(error); + }); + }, function (erro) { + erro.message = File.cordovaFileError[erro.code]; + rejectFn(erro); + }); + }, function (err) { + err.message = File.cordovaFileError[err.code]; + rejectFn(err); + }); + }, function (er) { + er.message = File.cordovaFileError[er.code]; + rejectFn(er); + }); + } catch (e) { + e.message = File.cordovaFileError[e.code]; + rejectFn(e); + } + + return promise; + } }