草庐IT

javascript - 如何从 Firefox 的上传处理程序中过滤掉目录?

coder 2025-04-01 原文

问题

我有以下代码片段用于在文件拖放上传期间获取文件信息:

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>`;
    });
}

我做了研究,发现 Firefox 不支持目录上传,但允许客户端将它们拖放到拖放区。

问题

如何从 Firefox 的上传处理程序中过滤掉目录?

更新

您可以在这里找到工作示例:https://jsfiddle.net/gevorgha/exs3ta25/

请考虑我需要它来处理 the latest stable Firefox version - 46.0.1无需从浏览器启用额外的首选项,因为我不想要求用户启用首选项以使上传正常工作。

最佳答案

My question would be is there any workaround for latest stable Firefox version to detect directories? Because on stable version that feature is disabled by default or do I miss something?

目录上传在 firefox 47 默认情况下未启用,已尝试 html , javascript在 stacksnippets,jsfiddle。

参见 Firefox 42 for developers Interfaces/APIs/DOM

The Directory interface has been experimentally extended (bug 1177688). The two members Directory.path and Directory.getContents can be exposed by setting the dom.input.dirpicker preference to true.

检测文件夹上传的解决方法可能包括

  1. 使用<input type="file">directoryallowdirs属性集,可能包括 multiple属性,参见 Note , 用于拖放或用户点击容器选择;
  2. 打开prefs.jsabout:config并设置 dom.input.dirpicker偏好 Boolean true ;
  3. Directory Upload Demo 为“1. 文件输入”使用“代码示例”的修改版本;
  4. 检查上传是否为 Directory 而不是一个File对象,使用 if有条件 (filesAndDirs[0] && filesAndDirs[0].constructor.name === "Directory")(filesAndDirs[0] instanceof Directory) .then(function(filesAndDirectories){}) 内部在链接到 .getFilesAndDirectories() ;
  5. 替代<label> <div> 的元素元素作为 <input type="file"> 的父元素.调整cssinput type="file"填充父级可放置容器并设置 opacity0 ;调整cssinput type="file" 的父元素中在 :before 处显示文本伪元素,超过 input type="file"子元素。

另见 New API for directory picking and drag-and-drop .

请注意,在 firefox 47 上尝试了该方法,目录和单个文件均已成功上传。

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) {
  event.stopPropagation();
  event.preventDefault();
  dropArea.className = "area";

  var uploadFile = function(file, path) {
    // handle file uploading
    console.log(file, path);
    var filesInfo = `<li>
                        Name: ${file.name}</br> 
                        Size: ${file.size} bytes</br> 
                        Type: ${file.type}</br> 
                        Modified Date: ${file.lastModifiedDate}
                      </li>`;
    ul.innerHTML += `${filesInfo}`;
  };

  var iterateFilesAndDirs = function(filesAndDirs, path) {
    for (var i = 0; i < filesAndDirs.length; i++) {
      if (typeof filesAndDirs[i].getFilesAndDirectories === 'function') {
        var path = filesAndDirs[i].path;

        // this recursion enables deep traversal of directories
        filesAndDirs[i].getFilesAndDirectories()
          .then(function(subFilesAndDirs) {
            // iterate through files and directories in sub-directory
            iterateFilesAndDirs(subFilesAndDirs, path);
          });
      } else {
        uploadFile(filesAndDirs[i], path);
      }
    }
  };
  if ("getFilesAndDirectories" in event.target) {
    event.target.getFilesAndDirectories()
      .then(function(filesAndDirs) {
        // if directory
        var dir = filesAndDirs;
        if (dir[0] && dir[0].constructor.name === "Directory") {
          
          console.log(dir);
          var directoryInfo = `<li>
                        Directory Name: ${dir[0].name}</br> 
                        Path: ${dir[0].path}
                      </li>`;
          ul.innerHTML += `${directoryInfo}`;
          alert("isDirectory:true");
        }
        iterateFilesAndDirs(dir, "/");
      })

  } else {
    // do webkit stuff
  }
}

dropArea.addEventListener("dragover", dragHandler);
dropArea.addEventListener("change", filesDroped);
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 here!\aOr click to select files";*/
  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;
}
<label id="dropArea" class="area">
  <input id="file" type="file" allowdirs directory webkitdirectory/>
</label>
<output id="result">
  <ul></ul>
</output>

jsfiddle https://jsfiddle.net/exs3ta25/31/

关于javascript - 如何从 Firefox 的上传处理程序中过滤掉目录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37443968/

有关javascript - 如何从 Firefox 的上传处理程序中过滤掉目录?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  4. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  6. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  9. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐