IS there any way to read the files and folder structure recursively starting from root.
The scope here is to scan all the files present in the directory along with there directory ,sub-directory using cordova
Take a look at the answer here: https://stackoverflow.com/a/29905718/346550. This is using the cordova file plugin.
scan : function(url,fileType,callback)
{
var fileTypeCollection = [];
var defer = $q.defer();
url.forEach(function(element, index)
{
//requestLocalFileSystemURL
log(element);
window.resolveLocalFileSystemURL(element,onRequestFileSystem, fail);
log("Ends resolve");
});
function onRequestFileSystem(fileSystem)
{
var directoryReader = fileSystem.createReader();
directoryReader.readEntries(onReadEntries,fail);
} /*onRequestFile Ends*/
function onReadEntries(entries)
{
if(entries.length==0)
{
log("Entries Length....Resolving");
defer.resolve(fileTypeCollection);
}
else
{
entries.forEach( function(element, index)
{
if (element.isDirectory === true)
{
// Recursive -- call back into this subdirectory
onRequestFileSystem(element);
}
if(element.isFile == true)
{
fileType.forEach(function(type)
{
if(element.name.indexOf(type) != -1)
{
fileTypeCollection.push(element);
}
});
} /*is File ENds*/
}); /*Entries For Each Ends*/
}
} /*OnRead Ends*/
function fail(resp)
{
log(resp);
defer.reject();
} /*Fail Ends*/
return defer.promise;
} //Scan Function Ends
have a look.This plugin can scan files based on filetype
https://github.com/siddmegadeth/Cordova-Media-Scanner
Related
How to search a specific named file in a folder using React ?
My file name is like below
var filename = window.location.hostname ;
Now I would like to search the file like below
if(require('../public/service/filename.json')) {
//do something
}
else {
//do something
}
You can use following way:
const checkFileExist = (path) => {
try {
return require(`${path}`);
} catch (err) {
return null;
}
};
and use it on your component
if(checkFileExist('../public/service/filename.json') === null) {
// something
} else {
// something
}
How to apply delay in JSZip API ? I want to zip multiple file. but I want to add some delay between transferring the files from webserver. How to add delay in below code?
This is for browser and deploying binaries inside the device.
$scope.download = function () {
var urls = ["/FILES/AlertLog.txt",
"/FILES/AuditLog.txt",
"/FILES/TotLog.txt",
"/FILES/Historian.csv",
"/FILES/History2.csv",
"/FILES/Factory.cfg",
"/FILES/SLog.txt",
"/FILES/se.dump",
"/FILES/AssertLog.txt",
"/FILES/History2.csv",
"/FILES/History3.csv",
"/FILES/History4.csv"
];
compress_files(urls);
}
function compress_files(urls) {
var zip = new JSZip();
var deferreds = [];
for (var i = 0; i < urls.length; i++) {
$timeout(function(){ deferreds.push(addToZip(zip, urls[i], i));
},200);// issue to deferreds variable =>undefined
$.when.apply(window, deferreds).done(generateZip);
}
function addToZip(zip, url, i) {
var deferred = $.Deferred();
JSZipUtils.getBinaryContent(url, function (err, data) {
if(err) {
deferred.resolve(zip);
}
else {
var arr=url.split("/");
zip.file(arr[2], data, { binary: true });
deferred.resolve(zip);
}
});
return deferred;
}
add some delay of milliseconds between transferring the files from the webserver.
I am trying to download the individual file by giving some delay. It fixed my problem
function downloadAll(files){
if(files.length == 0) return;
file = files.pop();
var theAnchor = $('<a />')
.attr('href', file[1])
.attr('download',file[0])
// Firefox does not fires click if the link is outside
// the DOM
.appendTo('body');
theAnchor[0].click();
theAnchor.remove();
downloadAll(files); }
function downloadAll(files){
if(files.length == 0) return;
file = files.pop();
var theAnchor = $('<a />')
.attr('href', file[1])
.attr('download',file[0])
// Firefox does not fires click if the link is outside
// the DOM
.appendTo('body');
theAnchor[0].click();
theAnchor.remove();
downloadAll(files);
}
$('a.download-csv').on('click', function(){
downloadAll([
['file1.csv', 'data:text/csv;charset=utf8,'+
encodeURIComponent('my,csv,file\and,so,on')],
['file2.txt', 'data:text/plain;charset=utf8,'+
encodeURIComponent('this script can do what I need.')],
['file3.js', 'data:text/javascriptcharset=utf8,'+
encodeURIComponent('alert(\'You can donate me your house if you like this script :-) \')')]
]);
});
I have I'm trying to write an AngularJS service which should work as singleton in storage files. There should be two methods:
for writing files by key getFilesForTabId
for getting saved files from setFilesForTabId
I'm trying to write something like this:
app.factory('fileStorage', ['LogService', function (LogService) {
var fileStorage = {
this.files = {};
this.getFilesForTabId = function (key) {
return this.files[key];
};
this.setFilesForTabId = function (key, files) {
this.files[key] = files;
return true;
}
}
return fileStorage;
}]);
But this code is bad. There are errors when I'm trying using it. How could I write it? I'd grateful for help
Now I have a problem with getFilesForTabId function. I'm trying to run this function with undefined files[key] object.
My actual service code is:
app.factory('fileStorage', ['LogService', function (LogService) {
var fileStorage = {
files: {},
setFilesForTabId: function(key,files){
this.files[key] = files;
return true;
},
getFilesForTabId: function (key) {
if(typeof(files[key]) === undefined) {
return [];
}
else{
return this.files[key];
}
}
}
return fileStorage;
}]);
Below I show error from browswer:
You can't use = in {} object.
var fileStorage =
{
files: {},
getFilesForTabId: function (key) {
return this.files[key];
},
setFilesForTabId: function (key, files) {
this.files[key] = files;
return true;
}
};
you are trying to initialize fileStorage as an object but are writing it like a function instead. you need to use Object Initializer Syntax.
Try this instead:
app.factory('fileStorage', ['LogService', function(LogService) {
var fileStorage = {
files: {},
getFilesForTabId: function(key) {
return this.files[key];
},
setFilesForTabId: function(key, files) {
this.files[key] = files;
return true;
},
};
return fileStorage;
}]);
I have tried to delete the whole directory(the folder + files under the folder) which files were downloaded into the external storage base directory: cordova.file.externalDataDirectory(like"file///storage/emulated/0/Android/data/com.yourapp/files").
But when I tried to remove the directory recursively by $cordovaFile,like below:
var baseDirectory = cordova.file.externalDataDirectory + 'attachments';
$cordovaFile.removeRecursively(baseDirectory,"")
.then(function(success){
console.log('Clear success');
},function(err){
loadingService.hideLoading();
})
It throws NO_MODIFICATION_ALLOWED error:
While I check the folder permission, I do have the write/execute right. Any one has any idea why this happens?
BTW, I have also tried the window.requestFileSystem, unfortunately, still don't work out.Since the filesystem is local file system, I tried to change the entry to external file system like
entry.nativeURL = cordova.file.externalDataDirectory;
But I guess it won't work since the reader has nothing there. So anyone has any suggestions on how to remove the whole directory?
Thanks in advance!
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemSuccess, fail);
function fail(evt) {
console.log("FILE SYSTEM FAILURE" + evt.target.error.code);
}
function onFileSystemSuccess(fileSystem) {
fileSystem.root.getDirectory(
"attachments",
{create : true, exclusive : false},
function(entry) {
console.log(entry);
entry.nativeURL = cordova.file.externalDataDirectory;
var reader = entry.createReader();
reader.readEntries(
function(entries){
console.log(entries);
},
function(err){
console.log(err);
}
)
entry.removeRecursively(function() {
console.log('CLEAR success');
}, fail);
}, fail);
}
In case you are using Android Marshmallow, ensure to use latest version of cordova file plugin (4.2.0) as it has issues fixes related to permissions. The code snippet for directory deletion is as follows,
function clearDirectory() {
if (ionic.Platform.isAndroid()) {
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, onFileSystemDirSuccess, fail);
} else {
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemDirSuccess, fail);
}
function onFileSystemDirSuccess(fileSystem) {
var entry = "";
if (ionic.Platform.isAndroid()) {
entry = fileSystem;
} else {
entry = fileSystem.root;
}
entry.getDirectory("DIRECTORY_TO_DELETE", {
create: true,
exclusive: false
},
function(entry) {
entry.removeRecursively(function() {
console.log("Remove Recursively Succeeded");
}, fail);
}, getDirFail);
}
function getDirFail(error) {
navigator.notification.alert("Error");
};
function fail(error) {
navigator.notification.alert("Error");
};
Depending on the use case, how do I constrain the number of files that dropzone.js will allow?
For example, I might need to only allow 1, 2, or 4 files uploaded.
It's not uploadMultiple. Unfortunately, uploadMultiple only applies to the number of files handled per request.
I achieved this a slightly different way. I just remove the old dropped file any time a new file is added. It acts as overwriting the file which was the user experience I was going for here.
Dropzone.options.myAwesomeDropzone = {
accept: function(file, done) {
console.log("uploaded");
done();
},
init: function() {
this.on("addedfile", function() {
if (this.files[1]!=null){
this.removeFile(this.files[0]);
}
});
}
};
Nowell pointed it out that this has been addressed as of August 6th, 2013. A working example using this form might be:
<form class="dropzone" id="my-awesome-dropzone"></form>
You could use this JavaScript:
Dropzone.options.myAwesomeDropzone = {
maxFiles: 1,
accept: function(file, done) {
console.log("uploaded");
done();
},
init: function() {
this.on("maxfilesexceeded", function(file){
alert("No more files please!");
});
}
};
The dropzone element even gets a special style, so you can do things like:
<style>
.dz-max-files-reached {background-color: red};
</style>
I thought that the most intuitive single file upload process was to replace the previous file upon a new entry.
$(".drop-image").dropzone({
url: '/cart?upload-engraving=true',
maxFiles: 1,
maxfilesexceeded: function(file) {
this.removeAllFiles();
this.addFile(file);
}
})
maxFiles: 1 does the job but if you also want to remove the additional files you can use this sample code taken from the Wiki page:
How can I limit the number of files?
You're in luck! Starting with 3.7.0 Dropzone supports the maxFiles
option. Simply set it to the desired quantity and you're good to go.
If you don't want the rejected files to be viewed, simply register for
the maxfilesexceeded event, and remove the file immediately:
myDropzone.on("maxfilesexceeded", function(file)
{
this.removeFile(file);
});
Alternative solution that worked really well for me:
init: function() {
this.on("addedfile", function(event) {
while (this.files.length > this.options.maxFiles) {
this.removeFile(this.files[0]);
}
});
}
You can limit the number of files uploaded by changing in dropezone.js
Dropzone.prototype.defaultOptions = {
maxFiles: 10,
}
Set maxFiles Count: maxFiles: 1
In maxfilesexceeded event, clear all files and add a new file:
event: Called for each file that has been rejected because the number
of files exceeds the maxFiles limit.
var myDropzone = new Dropzone("div#yourDropzoneID", { url: "/file/post",
uploadMultiple: false, maxFiles: 1 });
myDropzone.on("maxfilesexceeded", function (file) {
myDropzone.removeAllFiles();
myDropzone.addFile(file);
});
it looks like maxFiles is the parameter you are looking for.
https://github.com/enyo/dropzone/blob/master/src/dropzone.coffee#L667
Why do not you just use CSS to disable the click event. When max files is reached, Dropzone will automatically add a class of dz-max-files-reached.
Use css to disable click on dropzone:
.dz-max-files-reached {
pointer-events: none;
cursor: default;
}
Credit: this answer
The problem with the solutions provided is that you can only upload 1 file ever. In my case I needed to upload only 1 file at a time (on click or on drop).
This was my solution..
Dropzone.options.myDropzone = {
maxFiles: 2,
init: function() {
this.handleFiles = function(files) {
var file, _i, _len, _results;
_results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
_results.push(this.addFile(file));
// Make sure we don't handle more files than requested
if (this.options.maxFiles != null && this.options.maxFiles > 0 && _i >= (this.options.maxFiles - 1)) {
break;
}
}
return _results;
};
this._addFilesFromItems = function(items) {
var entry, item, _i, _len, _results;
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {
if (entry.isFile) {
_results.push(this.addFile(item.getAsFile()));
} else if (entry.isDirectory) {
_results.push(this._addFilesFromDirectory(entry, entry.name));
} else {
_results.push(void 0);
}
} else if (item.getAsFile != null) {
if ((item.kind == null) || item.kind === "file") {
_results.push(this.addFile(item.getAsFile()));
} else {
_results.push(void 0);
}
} else {
_results.push(void 0);
}
// Make sure we don't handle more files than requested
if (this.options.maxFiles != null && this.options.maxFiles > 0 && _i >= (this.options.maxFiles - 1)) {
break;
}
}
return _results;
};
}
};
Hope this helps ;)
I'd like to point out. maybe this just happens to me, HOWEVER, when I use this.removeAllFiles() in dropzone, it fires the event COMPLETE and this blows, what I did was check if the fileData was empty or not so I could actually submit the form.
You can also add in callbacks - here I'm using Dropzone for Angular
dzCallbacks = {
'addedfile' : function(file){
$scope.btSend = false;
$scope.form.logoFile = file;
},
'success' : function(file, xhr){
$scope.btSend = true;
console.log(file, xhr);
},
'maxfilesexceeded': function(file) {
$timeout(function() {
file._removeLink.click();
}, 2000);
}
}
Dropzone.options.dpzSingleFile = {
paramName: "file", // The name that will be used to transfer the file
maxFiles: 1,
init: function() {
this.on("maxfilesexceeded", function(file) {
this.removeAllFiles();
this.addFile(file);
});
}
};