0

I want to create my own drag and drop component and i use this: Does HTML5 allow drag-drop upload of folders or a folder tree? everything works fine, but i want to find out when files traverse is over, because i want to create an array of string, which contains file names and then do sth. traverseFileTree function contains callbacks so there are async tasks. I need to wait until callbacks are done and i don't know how to do it. I would use jQuery.Deffered but traverseFileTree is called from a loop and -in addition- this is a recursive function.

this.dndElement.addEventListener('drop', (ev: any) => {
  var items = ev.dataTransfer.items;
  for (var i = 0; i < items.length; i++) {
     this.traverseFileTree(items[i].webkitGetAsEntry());
  }

  // i want to wait until callbacks in the traverseFileTree are done and do sth with fileNames array 
});


public traverseFileTree(item, path?) {
        path = path || "";

        if (item.isFile) {
            item.file((file) => {
                this.fileNames.push(file.name);
            });
        } else if (item.isDirectory) {
            var dirReader = item.createReader();
            dirReader.readEntries((entries) => {
                for (var j = 0; j < entries.length; ++j) {
                    this.traverseFileTree(entries[j], path + item.name + "/");
                }
            });
        }
    }

UPDATE:

I did sth like this:

this.dndElement.addEventListener('drop', (ev: any) => {
            var items = ev.dataTransfer.items;

            for (var i = 0; i < items.length; i++) {
                var item = items[i].webkitGetAsEntry();
                if (item) {
                    this.traverseFileTree(item);
                }
            }

            Promise.all(this.promises).then(() => { console.log(this.fileNames); });

        });


public traverseFileTree(item, path?) {
        path = path || "";
        console.log(item);
        if (item.isFile) {
            this.fileNames.push(item.fullPath);
        } else if (item.isDirectory) {
            this.promises.push(new Promise((resolve, rejected) => {
                var dirReader = item.createReader();
                dirReader.readEntries((entries) => {
                    for (var j = 0; j < entries.length; ++j) {
                        this.traverseFileTree(entries[j], path + item.name + "/");
                    }
                    resolve();        
                })
            }));
        }
    }

and now i get list of files ... but only from "first level".

Adir
   Bdir
     1File
     2File
     Cdir
       3File
       4File
   5File
   6File

And i get 1File,2File,5File,6File but 3File,4File don't. Why?

Community
  • 1
  • 1
johndorian
  • 41
  • 3

1 Answers1

0

You kick off here :

this.traverseFileTree(items[i].webkitGetAsEntry());

And then the function public traverseFileTree(item, path?) { takes over. The function is sync (even though its recursive). Once it returns you should already be in good shape

However please note that this is webkit only :https://developer.mozilla.org/en/docs/Web/API/DirectoryReader#readEntries and is likely to be removed at some point.

basarat
  • 261,912
  • 58
  • 460
  • 511
  • When the loop is over, length of fileNames array is 0 so things happen asynchronously ... I just want to wait until every file name of traversed files is added to fileName array and then do sth with this array. Is any universal solution to drop files or folders to div and then create array of files name? – johndorian Feb 03 '16 at 13:44