关键词:
【中文标题】如何使用更改和删除事件在 firefox 和 chrome/chromium 上上传和列出目录【英文标题】:How to upload and list directories at firefox and chrome/chromium using change and drop events 【发布时间】:2017-02-01 13:03:04 【问题描述】:mozilla 和 webkit 浏览器现在都允许上传目录。当在<input type="file">
元素处选择一个或多个目录或在一个元素处拖放时,如何在firefox和chrome/chromium中按照它们在实际目录中出现的顺序列出所有目录和文件,并在所有上传目录时对文件执行任务迭代了吗?
【问题讨论】:
你还缺少什么信息? @KScandrett 没有关于从 firefox 或 chromium 的目录创建文件数组,这是我知道的。 Answer 中的listDirectory()
和listFile()
函数可能仍需要改进,以便在每个浏览器中获取和列出准确的结果。上次处理这些函数时,如果没记错的话,要获得文件对象的正确父目录是一项挑战,其中包含文件的目录也包含目录。 Answer 有一个TODO
,主要尝试了chromium的listDirectories()
和listFiles()
@KScandrett 如果您开发了与当前答案不同的方法来满足要求,请发布您的答案
@KScandrett 决定不选择“要求的规范答案”,这可能是适用的,因为已经编写了自己的答案来获取文件作为问题的单个数组部分;潜在地查看其他 SO 查看器和用户如何处理将文件作为单个数组获取并在 HTML 中创建呈现的目录和文件树的要求,从而在 chromium/chrome 和 firefox 浏览器中一致地准确反映上传的文件夹的目录树。
【参考方案1】:
您可以在<input type="file">
元素处设置webkitdirectory
和allowdirs
属性;将change
、drop
事件附加到<input type="file">
元素;在 mozilla 中使用 .getFilesAndDirectories()
,.createReader()
,.readEntries()
webkit
,Array.prototype.reduce()
,Promise
,递归。
注意 firefox drop
事件不会将选择列为Directory
,而是将File
对象列为具有size
0
的对象,因此在firefox 中删除目录不提供已删除文件夹的表示,即使在@使用 987654340@。当设置allowdirs
属性时,firefox 还提供了两个输入元素;第一个元素允许上传单个文件,第二个元素允许上传目录。 chrome/chromium 提供单个 <input type="file">
元素,其中只能选择单个或多个目录,而不是单个文件。
在同时包含文件和目录的目录中,首先读取目录。
<!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 mozResult = [];
var files;
console.log(event);
event.stopPropagation();
event.preventDefault();
dropArea.className = "area";
// do mozilla stuff
// TODO adjust, call `listDirectory()`, `listFile()`
function mozReadDirectories(entries, path)
console.log("dir", entries, path);
return [].reduce.call(entries, function(promise, entry)
return promise.then(function()
return Promise.resolve(entry.getFilesAndDirectories() || entry)
.then(function(dir)
return dir
)
)
, Promise.resolve())
.then(function(items)
var dir = items.filter(function(folder)
return folder instanceof Directory
);
var files = items.filter(function(file)
return file instanceof File
);
if (files.length)
// console.log("files:", files, path);
files.forEach(function(file)
console.log(file)
);
mozResult = mozResult.concat.apply(mozResult, files);
if (dir.length)
// console.log(dir, dir[0] instanceof Directory);
return mozReadDirectories(dir, dir[0].path || path);
else
if (!dir.length)
return Promise.resolve(mozResult).then(function(complete)
return complete
)
)
;
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);
// TODO: handle mozilla directories, additional directories being selected dropped and listed without
// creating nested list at `html` where different directory selected or dropped
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)
if (!document.getElementsByClassName(cname).length)
var directoryInfo = `<li><ul class=$cname>
<li>
<span>
Directory Name: $entry.name<br>
Path: $path
<hr>
</span>
</li></ul></li>`;
var curr = document.getElementsByTagName("ul");
var _ul = curr[curr.length - 1];
var _li = _ul.querySelectorAll("li");
if (!document.querySelector("[class*=" + cname + "]"))
if (_li.length)
_li[_li.length - 1].innerHTML += `$directoryInfo`;
else
_ul.innerHTML += `$directoryInfo`
else
ul.innerHTML += `$directoryInfo`
return Promise.resolve(entry);
// TODO: handle mozilla files
function listFile(file, path)
path = path || file.webkitRelativePath || "/" + file.name;
var filesInfo = `<li>
Name: $file.name</br>
Size: $file.size bytes</br>
Type: $file.type</br>
Modified Date: $file.lastModifiedDate<br>
Full Path: $path
</li>`;
var currentPath = path.split("/").filter(Boolean);
currentPath.pop();
var appended = false;
var curr = document.getElementsByClassName(`$currentPath.join("-")`);
if (curr.length)
for (li of curr[curr.length - 1].querySelectorAll("li"))
if (li.innerHTML.indexOf(path.slice(0, path.lastIndexOf("/"))) > -1)
li.querySelector("span").insertAdjacentHTML("afterend", `$filesInfo`);
appended = true;
break;
if (!appended)
curr[curr.length - 1].innerHTML += `$filesInfo`;
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)
)
.catch(function(err)
alert(err.message);
)
if ("getFilesAndDirectories" in event.target)
return (event.type === "drop" ? event.dataTransfer : event.target).getFilesAndDirectories()
.then(function(dir)
if (dir[0] instanceof Directory)
console.log(dir)
return mozReadDirectories(dir, dir[0].path || path)
.then(function(complete)
console.log("complete:", complete);
event.target.value = null;
);
else
if (dir[0] instanceof File && dir[0].size > 0)
return Promise.resolve(dir)
.then(function(complete)
console.log("complete:", complete);
)
else
if (dir[0].size == 0)
throw new Error("could not process '" + dir[0].name + "' directory"
+ " at drop event at firefox, upload folders at 'Choose folder...' input");
).catch(function(err)
alert(err)
)
// 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>
plnkrhttp://plnkr.co/edit/ff5vmuuIMzSapu6MiUJ3?p=preview
【讨论】:
见File and Directory Entry API在 NextJs 中如何使用更改事件更改 getServerSideProps
】在NextJs中如何使用更改事件更改getServerSideProps【英文标题】:InNextJshowtochangegetServerSidePropswithchangeevent【发布时间】:2021-01-1303:10:14【问题描述】:这里我正在尝试根据类别更改产品数据,我有一个索引页和两个名为Products和Cat... 查看详情
使用 FireFox、Safari 和 Chrome 在剪贴板上复制/放置文本
】使用FireFox、Safari和Chrome在剪贴板上复制/放置文本【英文标题】:Copy/PuttextontheclipboardwithFireFox,SafariandChrome【发布时间】:2010-09-1217:25:12【问题描述】:在InternetExplorer中,我可以使用clipboardData对象访问剪贴板。如何在FireFox、Sa... 查看详情
如何使用 C# 在文件观察器中捕获剪切和粘贴操作
】如何使用C#在文件观察器中捕获剪切和粘贴操作【英文标题】:HowtocapturecutandpasteactioninfilewatcherusingC#【发布时间】:2012-05-2312:31:11【问题描述】:我编写了文件观察器功能来专注于特定的目录活动。我可以阅读所有事件,如创... 查看详情
如何在 C++ 中监听智能卡插入和删除事件?
】如何在C++中监听智能卡插入和删除事件?【英文标题】:HowdoIlistenforsmartcardinsertandremoveeventinC++?【发布时间】:2011-11-2307:55:29【问题描述】:我想监听智能购物车的插入和删除事件...该应用程序适用于Windows,智能卡使用x.509证... 查看详情
在firefox中使用'deviceorientation'事件会发出警告(代码片段)
在firefox60控制台中运行以下代码时,会给我一条警告消息“不推荐使用方向传感器”。window.addEventListener('deviceorientation',function(event)console.log(event.alpha+':'+event.beta+':'+event.gamma););在firefox60和61(Beta)上在Windows和Mac上试过这个。警... 查看详情
如何在sqlalchemy中的值更改后触发事件
】如何在sqlalchemy中的值更改后触发事件【英文标题】:Howtotriggeraneventaftervaluechangeinsqlalchemy【发布时间】:2020-12-0417:56:38【问题描述】:我正在使用sqlalchemy定义一个映射类。它包含三个用户定义的值(a、b、c)和一个依赖值(ab... 查看详情
如何在 Firefox 中删除 SELECT/OPTION 下拉控件上的虚线?
】如何在Firefox中删除SELECT/OPTION下拉控件上的虚线?【英文标题】:HowcanIremovethedottedlinesonaSELECT/OPTIONdropdowncontrolinFirefox?【发布时间】:2011-06-2206:06:34【问题描述】:在Chrome和其他浏览器中,我的下拉菜单看起来很好:但是,在Fi... 查看详情
如何存储在Java中执行事件后更改的变量的最终值
】如何存储在Java中执行事件后更改的变量的最终值【英文标题】:howtostorethefinalvalueofavariablewhichchangesafteraneventisperformedinJava【发布时间】:2021-05-0919:22:26【问题描述】:我正在使用Swing和AWT组件开发Java睡眠周期计算器应用程序... 查看详情
在 firefox 中设置复选框的样式 - 删除检查和边框
】在firefox中设置复选框的样式-删除检查和边框【英文标题】:Styleacheckboxinfirefox—removecheckandborder【发布时间】:2013-10-0908:14:38【问题描述】:如何在Firefox中设置复选框的样式,并使复选标记和边框消失?http://jsfiddle.net/moneyloti... 查看详情
在 xul 和 javascript 中通过按钮单击事件上的另一个工具提示文本更改工具提示文本
...发布时间】:2011-03-0206:09:13【问题描述】:嗨我正在创建Firefox插件。我在Firefox网络浏览器的工具栏上创建了一个按钮图像。我已经为按钮分配了一个toolti 查看详情
检查设备更改(添加/删除)事件
...标或其他任何东西。我尝试四处搜索,但找不到任何说明如何执行此操作的内容。有什么想法吗?【问题讨论】:我制作了一个适用于Windows、MacOS和Linux的N 查看详情
检查设备更改(添加/删除)事件
...标或其他任何东西。我尝试四处搜索,但找不到任何说明如何执行此操作的内容。有什么想法吗?【问题讨论】:我制作了一个适用于Windows、MacOS和Linux的N 查看详情
如何使用 css 和/或 javascript 动态更改样式
】如何使用css和/或javascript动态更改样式【英文标题】:Howtodynamicchangestyleswithcssand/orjavascript【发布时间】:2019-08-1809:58:59【问题描述】:我有一个按钮,我需要在单击它时更改一些样式。我可能可以通过添加和删除一些类轻松... 查看详情
如何在 Selenium 的无头 Firefox 中使用 --screenshot 和 python
】如何在Selenium的无头Firefox中使用--screenshot和python【英文标题】:Howtouse--screenshotinheadlessfirefoxinSeleniumwithpython【发布时间】:2018-06-2301:07:50【问题描述】:使用@DebanjanB在HowtomakefirefoxheadlessprogramaticallyinSeleniumwithpython?中的回复,... 查看详情
在页面内容更改时停止自动滚动
...页面,它在滚动事件中向自身添加和删除一些内容。现在使用Chrome时(IE11似乎没有这种行为),每当向页面添加和删除内容时,都会生成滚动事件(我猜是为了保持客户端视图在页面更改时保持一致)。我不想要这个。内容变... 查看详情
如何使用 JavaScript 在 Firefox 中触发鼠标滚轮事件?
】如何使用JavaScript在Firefox中触发鼠标滚轮事件?【英文标题】:HowtofiremousewheeleventinFirefoxwithJavaScript?【发布时间】:2011-10-0719:52:21【问题描述】:我正在尝试使用WebDriver进行自动化测试,但它目前无法模拟鼠标滚轮事件。作为... 查看详情
更改视图的 y 位置会删除点击事件
...齐,并偏移-154,因此它在屏幕外)。当应用启动时,我使用一个按钮将整个根视图向上移动self.view.center.y-=154根视图和我的UIView都出现在预 查看详情
知道如何在 Firefox 和 ie 上使用可用的 webkit 填充吗?
】知道如何在Firefox和ie上使用可用的webkit填充吗?【英文标题】:Anyideahowtousewebkitfillavailableworkingonfirefoxandie?【发布时间】:2019-03-0404:51:45【问题描述】:我使用css:width:-webkit-fill-available;height:-webkit-fill-available;对于我的图像,... 查看详情