diff --git a/README.md b/README.md index 8a220dd..2afe9a6 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,15 @@ Are you entangled in a async callback mess to get even the simplest task done? W cordova plugin add cordova-plugin-file-transfer # optional ``` +### mi-corporation change +This fork differs from the original repository in the following ways: +- 2018: write -- don't convert text to Blob +- 2018: normalize -- avoid appending slash to any path that has a dot in any segment, not just last segment +- 2018: read -- Handle FileReader errors instead of resolving with null +- 2024: when accessing the local file system in Android, default to the file:// prefix instead of http://. The reason for this fix is described here: +https://github.com/apache/cordova-plugin-file-transfer/issues/378 + + **IMPORTANT:** For iOS, use Cordova 3.7.0 or higher (due to a [bug](https://github.com/AppGyver/steroids/issues/534) that affects requestFileSystem). Or just download and include [CordovaPromiseFS.js](https://raw.githubusercontent.com/markmarijnissen/cordova-promise-fs/master/dist/CordovaPromiseFS.js). diff --git a/dist/CordovaPromiseFS.js b/dist/CordovaPromiseFS.js index 860be92..01cea67 100644 --- a/dist/CordovaPromiseFS.js +++ b/dist/CordovaPromiseFS.js @@ -101,11 +101,10 @@ function normalize(str){ str = str || ''; if(str[0] === '/') str = str.substr(1); - var tokens = str.split('/'), last = tokens[0]; + var tokens = str.split('/'); // check tokens for instances of .. and . for(var i=1;i < tokens.length;i++) { - last = tokens[i]; if (tokens[i] === '..') { // remove the .. and the previous token tokens.splice(i-1,2); @@ -122,7 +121,7 @@ function normalize(str){ str = tokens.join('/'); if(str === './') { str = ''; - } else if(last && last.indexOf('.') < 0 && str[str.length - 1] != '/'){ + } else if(str && str.indexOf('.') < 0 && str[str.length - 1] != '/'){ str += '/'; } return str; @@ -153,7 +152,8 @@ module.exports = function(options){ /* Cordova deviceready promise */ var deviceready, isCordova = typeof cordova !== 'undefined' && !options.crosswalk, - isCrosswalk = options.crosswalk; + isCrosswalk = options.crosswalk, + isAndroid = isCordova && !/MSAppHost/.test(navigator.userAgent) && /Android/.test(navigator.userAgent); if(isCordova){ deviceready = new Promise(function(resolve,reject){ document.addEventListener("deviceready", resolve, false); @@ -239,7 +239,7 @@ module.exports = function(options){ /* debug */ fs.then(function(fs){ - CDV_URL_ROOT = fs.root.toURL(); + CDV_URL_ROOT = isAndroid ? fs.root.nativeURL : fs.root.toURL(); CDV_INTERNAL_URL_ROOT = isCordova? fs.root.toInternalURL(): CDV_URL_ROOT; window.__fs = fs; },function(err){ @@ -388,6 +388,8 @@ module.exports = function(options){ /* convert path to URL to be used in JS/CSS/HTML */ function toURL(path) { return file(path).then(function(fileEntry) { + // NOTE: we would expect Android to require fileEntry.nativeURL instead of fileEntry.toURL() because it requires the file:// naming scheme rather than http:// + // however, if we return fileEntry.nativeURL here then the Image Annotation field fails to load images; so leave as is for now since it works return fileEntry.toURL(); }); } @@ -447,7 +449,12 @@ module.exports = function(options){ fileEntry.file(function(file){ var reader = new FileReader(); reader.onloadend = function(){ - resolve(this.result); + // Handle errors as well as successes + if (reader.error) { + reject(reader.error); + } else { + resolve(reader.result); + } }; reader[method](file); },reject); @@ -475,9 +482,10 @@ module.exports = function(options){ writer.onwriteend = resolve; writer.onerror = reject; if(typeof blob === 'string') { - blob = createBlob([blob], mimeType || 'text/plain'); + // blob = createBlob([blob], mimeType || 'text/plain'); } else if(blob instanceof Blob !== true){ - blob = createBlob([JSON.stringify(blob,null,4)], mimeType || 'application/json'); + // blob = createBlob([JSON.stringify(blob,null,4)], mimeType || 'application/json'); + blob = JSON.stringify(blob,null,4); } writer.write(blob); },reject); diff --git a/index.js b/index.js index 900b9a9..6e3b4f4 100644 --- a/index.js +++ b/index.js @@ -28,11 +28,10 @@ function normalize(str){ str = str || ''; if(str[0] === '/') str = str.substr(1); - var tokens = str.split('/'), last = tokens[0]; + var tokens = str.split('/'); // check tokens for instances of .. and . for(var i=1;i < tokens.length;i++) { - last = tokens[i]; if (tokens[i] === '..') { // remove the .. and the previous token tokens.splice(i-1,2); @@ -49,7 +48,7 @@ function normalize(str){ str = tokens.join('/'); if(str === './') { str = ''; - } else if(last && last.indexOf('.') < 0 && str[str.length - 1] != '/'){ + } else if(str && str.indexOf('.') < 0 && str[str.length - 1] != '/'){ str += '/'; } return str; @@ -80,7 +79,8 @@ module.exports = function(options){ /* Cordova deviceready promise */ var deviceready, isCordova = typeof cordova !== 'undefined' && !options.crosswalk, - isCrosswalk = options.crosswalk; + isCrosswalk = options.crosswalk, + isAndroid = isCordova && !/MSAppHost/.test(navigator.userAgent) && /Android/.test(navigator.userAgent); if(isCordova){ deviceready = new Promise(function(resolve,reject){ document.addEventListener("deviceready", resolve, false); @@ -150,7 +150,7 @@ module.exports = function(options){ window.requestFileSystem(type, grantedBytes, resolve, reject); }, reject); - // Exotic Cordova Directories (options.fileSystem = string) + // Exotic Cordova Directories (options.fileSystem = string) } else if(isNaN(type)) { window.resolveLocalFileSystemURL(type,function(directory){ resolve(directory.filesystem); @@ -166,7 +166,7 @@ module.exports = function(options){ /* debug */ fs.then(function(fs){ - CDV_URL_ROOT = fs.root.toURL(); + CDV_URL_ROOT = isAndroid ? fs.root.nativeURL : fs.root.toURL(); CDV_INTERNAL_URL_ROOT = isCordova? fs.root.toInternalURL(): CDV_URL_ROOT; window.__fs = fs; },function(err){ @@ -315,6 +315,8 @@ module.exports = function(options){ /* convert path to URL to be used in JS/CSS/HTML */ function toURL(path) { return file(path).then(function(fileEntry) { + // NOTE: we would expect Android to require fileEntry.nativeURL instead of fileEntry.toURL() because it requires the file:// naming scheme rather than http:// + // however, if we return fileEntry.nativeURL here then the Image Annotation field fails to load images; so leave as is for now since it works return fileEntry.toURL(); }); } @@ -374,7 +376,12 @@ module.exports = function(options){ fileEntry.file(function(file){ var reader = new FileReader(); reader.onloadend = function(){ - resolve(this.result); + // Handle errors as well as successes + if (reader.error) { + reject(reader.error); + } else { + resolve(reader.result); + } }; reader[method](file); },reject); @@ -402,9 +409,10 @@ module.exports = function(options){ writer.onwriteend = resolve; writer.onerror = reject; if(typeof blob === 'string') { - blob = createBlob([blob], mimeType || 'text/plain'); + // blob = createBlob([blob], mimeType || 'text/plain'); } else if(blob instanceof Blob !== true){ - blob = createBlob([JSON.stringify(blob,null,4)], mimeType || 'application/json'); + // blob = createBlob([JSON.stringify(blob,null,4)], mimeType || 'application/json'); + blob = JSON.stringify(blob,null,4); } writer.write(blob); },reject); @@ -539,7 +547,7 @@ module.exports = function(options){ transferOptions = {}; } if(isCordova && localPath.indexOf('://') < 0) localPath = toURLSync(localPath); - + transferOptions = transferOptions || {}; if(!transferOptions.retry || !transferOptions.retry.length) { transferOptions.retry = options.retry;