如何检测Chrome中何时上传空目录?

时间:2017-02-09 06:41:55

标签: javascript html5 google-chrome

我使用type =" file"创建了一个输入元素,其中包含多个,webkit目录,allowdirs和目录属性。

然后我添加了一个"更改"事件处理程序,当我选择要上传的文件目录时,它就可以工作。

但是,如果我不小心选择了一个空目录,我就不会收到更改事件。是否还有其他事件可用于检测是否已选择空目录?

我希望能够告诉用户所选目录是空的并尝试选择另一个目录。现在我无法检测到用户已经做了任何事情,并且用户没有被告知为什么他们的选择没有做任何事情。

据报道这是一个错误:

https://bugs.chromium.org/p/chromium/issues/detail?id=360412

但我想知道是否有解决方法。

1 个答案:

答案 0 :(得分:0)

您可以使用Directory构造函数在File事件处迭代dropPromise个实例,调度函数调用自身,将File实例推送到数组;如果在完成处理时数组.length等于0,则文件夹不包含文件。

另见How to upload and list directories at firefox and chrome/chromium using change and drop events



<!DOCTYPE html>
<html>

<head>
  <style type="text/css">
    input[type="file"] {
      width: 98%;
      height: 180px;
    }

    label[for="file"] {
      width: 98%;
      height: 180px;
    }

    .area {
      display: block;
      border: 5px dotted #ccc;
      text-align: center;
    }

    .area:after {
      display: block;
      border: none;
      white-space: pre;
      content: "Drop your files or folders here!\aOr click to select files folders";
      position: relative;
      left: 0%;
      top: -75px;
      text-align: center;
    }

    .drag {
      border: 5px dotted green;
      background-color: yellow;
    }

    #result ul {
      list-style: none;
      margin-top: 20px;
    }

    #result ul li {
      border-bottom: 1px solid #ccc;
      margin-bottom: 10px;
    }

    #result li span {
      font-weight: bold;
      color: navy;
    }
  </style>
</head>


<body>
  <label id="dropArea" class="area">
    <input id="file" type="file" directory allowdirs webkitdirectory/>
  </label>
  <output id="result">
    <ul></ul>
  </output>
  <script>
    var dropArea = document.getElementById("dropArea");
    var output = document.getElementById("result");
    var ul = output.querySelector("ul");

    function dragHandler(event) {
      event.stopPropagation();
      event.preventDefault();
      dropArea.className = "area drag";
    }

    function filesDroped(event) {
      var webkitResult = [];
      var files;
      console.log(event);
      event.stopPropagation();
      event.preventDefault();
      dropArea.className = "area";

      function handleEntries(entry) {
        let file = "webkitGetAsEntry" in entry ? entry.webkitGetAsEntry() : entry
        return Promise.resolve(file);
      }

      function handleFile(entry) {
        return new Promise(function(resolve) {
          if (entry.isFile) {
            entry.file(function(file) {
              listFile(file, entry.fullPath).then(resolve)
            })
          } else if (entry.isDirectory) {
            var reader = entry.createReader();
            reader.readEntries(webkitReadDirectories.bind(null, entry, handleFile, resolve))
          } else {
            var entries = [entry];
            return entries.reduce(function(promise, file) {
                return promise.then(function() {
                  return listDirectory(file)
                })
              }, Promise.resolve())
              .then(function() {
                return Promise.all(entries.map(function(file) {
                  return listFile(file)
                })).then(resolve)
              })
          }
        })

        function webkitReadDirectories(entry, callback, resolve, entries) {
          console.log(entries);
          return listDirectory(entry).then(function(currentDirectory) {
            console.log(`iterating ${currentDirectory.name} directory`, entry);
            return entries.reduce(function(promise, directory) {
              return promise.then(function() {
                return callback(directory)
              });
            }, Promise.resolve())
          }).then(resolve);
        }

      }
      
      function listDirectory(entry) {
        console.log(entry);
        var path = (entry.fullPath || entry.webkitRelativePath.slice(0, entry.webkitRelativePath.lastIndexOf("/")));
        var cname = path.split("/").filter(Boolean).join("-");
        console.log("cname", cname)

        return Promise.resolve(entry);
      }
       // TODO: handle mozilla files
      function listFile(file, path) {
        path = path || file.webkitRelativePath || "/" + file.name;

        console.log(`reading ${file.name}, size: ${file.size}, path:${path}`);
        webkitResult.push(file);
        return Promise.resolve(webkitResult)
      };

      function processFiles(files) {
        Promise.all([].map.call(files, function(file, index) {
            return handleEntries(file, index).then(handleFile)
          }))
          .then(function() {
            console.log("complete", webkitResult);
            if (webkitResult.length === 0) {
              alert("empty directory")
            }
          })
          .catch(function(err) {
            alert(err.message);
          })
      }

      // do webkit stuff
      if (event.type === "drop" && event.target.webkitdirectory) {
        files = event.dataTransfer.items || event.dataTransfer.files;
      } else if (event.type === "change") {
        files = event.target.files;
      }

      if (files) {
        processFiles(files)
      }

    }
    dropArea.addEventListener("dragover", dragHandler);
    dropArea.addEventListener("change", filesDroped);
    dropArea.addEventListener("drop", filesDroped);
  </script>
</body>

</html>
&#13;
&#13;
&#13;