1

I'm trying to upload folders using the FileSystem API.

dropzone.ondrop = function(e) {
                e.preventDefault();
                let items=e.dataTransfer.items;
                let formdata=new FormData();
                function scanFiles(item){
                    console.log("In scanFiles")
                    if (item.isFile) {
                        console.log("Typecasting...");

                        item.file(function(file) {
                            console.log(file);
                            formdata.append('directory',file);
                        });
                    }
                    else if (item.isDirectory) {
                        console.log("Directory...")
                        let directoryReader = item.createReader();
                        directoryReader.readEntries(function(entries) {
                            entries.forEach(function(entry) {
                                scanFiles(entry);
                            });
                        });
                    }
                }
                for (let i=0; i<items.length; i++) {
                    let item = items[i].webkitGetAsEntry();
                    console.log(item);
                    if (item) {
                        console.log("Calling scan");
                        scanFiles(item);
                        console.log("Ending scan");
                    }
                }

                var xhr=new XMLHttpRequest();
                xhr.open('post','uploadFolder/');
                xhr.send(formdata);
            }

Basically, what the code does is take a dropped folder, read its contents and if its a file, attaches it as a file input to a form, and send it to the required url for further processing. Okay, so the problem is when I run it, the console output is

FileSystemFileEntry { isFile: true, isDirectory: false, name: "Test.o", fullPath: "/Test.o", filesystem: FileSystem }  
Calling scan  
In scanFiles  
Typecasting...  
Ending scan  
File { name: "Test.o", lastModified: 1506856693000, lastModifiedDate: Date 2017-10-01T11:18:13.000Z, webkitRelativePath: "", size: 6240, type: "" }

The file object is created after all lines in the script have been executed and so an incorrect request is sent to the url.

I guess this is due to the closure nature of the file() function. Can someone please tell me how I can get the file input in the proper manner?

0

1 Answer 1

2

.file() function is asynchronous. You can use Promise constructor and Promise.all() to await all calls to .file(), see also How to upload and list directories at firefox and chrome/chromium using change and drop events

HTML

<input type="file" webkitdirectory>

JavaScript

var dropzone = document.querySelector("input[type=file]");

dropzone.ondrop = function(e) {
  e.preventDefault();
  let items = e.dataTransfer.items;
  let formdata = new FormData();

  function scanFiles(item, index) {
    return new Promise(function(resolve) {
      if (item.isFile) {
        console.log("Typecasting...", item);

        item.file(function(file) {
          console.log(file, "here");
          formdata.append('file-' + index, file);
          resolve();
        });
      } else if (item.isDirectory) {
        console.log("Directory...")
        let directoryReader = item.createReader();

        directoryReader.readEntries(function(entries) {
          Promise.all(entries.map(scanFiles)).then(resolve);
        });
      }
    })
  }

  var p = Promise.all(Array.from(items, item => scanFiles(item.webkitGetAsEntry())));
  p.then(function() {
    // do stuff with `formdata` here
    for (let prop of formdata) {
      console.log(prop[0], prop[1])
    }
    /*
      var xhr=new XMLHttpRequest();
      formdata.append('address','');
      xhr.open('post','uploadFolder/');
      xhr.send(formdata);
    */
  })

}

jsfiddle https://jsfiddle.net/t03bvbzu/

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I was looking for a working solution everywhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.