Search code examples
javascriptfirefoxfile-uploadmozilladirectory-upload

How can I filter out directories from upload handler in Firefox?


Problem

I have following code snippet that is used to get file information during file drag and drop upload:

var files = event.dataTransfer.files;

for (var i = 0; i < files.length; i++) {
    var file = files[i];

    // I need notDirectory(file) function.
    notDirectory(file).then(function(file) {
      output.innerHTML += 
           `<p>
              Name: ${file.name}</br> 
              Size: ${file.size} bytes</br> 
              Type: ${file.type}</br> 
              Modified Date: ${file.lastModifiedDate}
            </p>`;
    });
}

I did research and found that Firefox does not support directory uploads, but allows client to drag and drop them to drop area.

Question

How can I filter out directories from upload handler in Firefox?

Update

You can find working sample here: https://jsfiddle.net/gevorgha/exs3ta25/

Please consider that I need it to work on the latest stable Firefox version - 46.0.1 without enabling extra preferences from browser, because I don't want to ask users to enable preference to make upload work properly.


Solution

  • Solution

    I came up with following dirty workaround that works on Firefox version - 46.0.1

    It uses FileReader API to check if uploaded file is directory or not.

    Code

    <div id="dropArea" style="border: 1px solid; padding: 50px; text-align: center;">
        Drop your files here!
    </div>
    
    <script>
        // Get target elements.
        var dropArea = document.getElementById("dropArea");
    
        // To be defined.
        function notDirectory(file) {
            return new Promise(function(resolve, reject) {
                var reader = new FileReader();
    
                // Can read files, but not directories.
                reader.onprogress = function(event) {
                    if ('progress' === event.type) {
                        resolve(file);
                        reader.abort();
                    }
                };
    
                // Wait for result.
                reader.readAsDataURL(file);
            });
        }
    
        // Attach drop listener.
        dropArea.addEventListener("drop", function (event) {
            // Stop propagation.
            event.stopPropagation();
            event.preventDefault();
    
            // Loop files to filter out directories and print files.
            var files = event.dataTransfer.files;
            for (var i = 0; i < files.length; i++) {
                var file = files[i];
    
                // I need notDirectory(file) function.
                notDirectory(file).then(function(file) {
                    // Print info.
                    console.log({
                        name: file.name,
                        size: file.size,
                        type: file.type
                    });
                });
            }
        });
    
        // Attach drag move listener.
        dropArea.addEventListener("dragover", function (event) {
            // Stop propagation.
            event.stopPropagation();
            event.preventDefault();
        });
    </script>

    Related Links