如何从 Firefox 的上传处理程序中过滤掉目录?
How can I filter out directories from upload handler in Firefox?
问题
我有以下代码片段,用于在文件拖放上传期间获取文件信息:
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/
请考虑我需要它才能在 最新稳定的 Firefox 版本上工作 -
46.0.1 没有从浏览器启用额外的首选项,因为我不想让用户启用首选项来使上传正常工作。
您可以在 here(包括 Firefix)中阅读一些相关内容。这是一个函数(不是我做的,但我可能编辑了一半)检测 drop 是文件还是文件夹并显示它的名称、大小和类型(在 FireFox 中测试):
function handleDrop(e)
{
e.stopPropagation();
e.preventDefault();
var filesInfo = "";
var files = e.dataTransfer.files,
folder;
for (var i = 0, f; f = files[i]; i++)
{
if (!f.type && f.size % 4096 == 0)
folder = true;
else
folder = false;
filesInfo += 'Name: ' + f.name;
filesInfo += '<br>Size: ' + f.size + ' bytes';
filesInfo += '<br>Type: ' + (folder ? 'folder ' : 'file');
output.innerHTML = filesInfo;
}
}
我希望这就是您要找的。祝你好运!
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 默认不启用目录上传,在 stacksnippets、jsfiddle 中尝试 html
、javascript
。
见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
.
检测文件夹上传的解决方法可能包括
- 将
<input type="file">
与 directory
和 allowdirs
属性集一起使用,可能包括 multiple
属性,参见 Note,用于拖放或用户选择单击容器;
- 打开
prefs.js
或 about:config
并将 dom.input.dirpicker
首选项设置为 Boolean
true
;
- 使用 "Code example" 的修改版本用于 Directory Upload Demo 的“1. 文件输入”;
- 检查上传是否为
Directory
and not a single File
object, use if
with condition (filesAndDirs[0] && filesAndDirs[0].constructor.name === "Directory")
or (filesAndDirs[0] instanceof Directory)
inside of .then(function(filesAndDirectories){})
at chained to .getFilesAndDirectories()
;
- 用
<label>
元素替换 <div>
元素作为 <input type="file">
的父元素。调整 input type="file"
的 css
以填充父级可放置容器并将 opacity
设置为 0
;在 input type="file"
的父元素上调整 css
以在 :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/
解决方案
我想出了以下适用于 Firefox version - 46.0.1
的肮脏解决方法
它使用FileReader API检查上传的文件是否是目录。
代码
<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>
相关链接
问题
我有以下代码片段,用于在文件拖放上传期间获取文件信息:
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/
请考虑我需要它才能在 最新稳定的 Firefox 版本上工作 - 46.0.1 没有从浏览器启用额外的首选项,因为我不想让用户启用首选项来使上传正常工作。
您可以在 here(包括 Firefix)中阅读一些相关内容。这是一个函数(不是我做的,但我可能编辑了一半)检测 drop 是文件还是文件夹并显示它的名称、大小和类型(在 FireFox 中测试):
function handleDrop(e)
{
e.stopPropagation();
e.preventDefault();
var filesInfo = "";
var files = e.dataTransfer.files,
folder;
for (var i = 0, f; f = files[i]; i++)
{
if (!f.type && f.size % 4096 == 0)
folder = true;
else
folder = false;
filesInfo += 'Name: ' + f.name;
filesInfo += '<br>Size: ' + f.size + ' bytes';
filesInfo += '<br>Type: ' + (folder ? 'folder ' : 'file');
output.innerHTML = filesInfo;
}
}
我希望这就是您要找的。祝你好运!
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 默认不启用目录上传,在 stacksnippets、jsfiddle 中尝试 html
、javascript
。
见Firefox 42 for developers Interfaces/APIs/DOM
The
Directory
interface has been experimentally extended (bug 1177688). The two membersDirectory.path
andDirectory.getContents
can be exposed by setting thedom.input.dirpicker
preference totrue
.
检测文件夹上传的解决方法可能包括
- 将
<input type="file">
与directory
和allowdirs
属性集一起使用,可能包括multiple
属性,参见 Note,用于拖放或用户选择单击容器; - 打开
prefs.js
或about:config
并将dom.input.dirpicker
首选项设置为Boolean
true
; - 使用 "Code example" 的修改版本用于 Directory Upload Demo 的“1. 文件输入”;
- 检查上传是否为
Directory
and not a singleFile
object, useif
with condition(filesAndDirs[0] && filesAndDirs[0].constructor.name === "Directory")
or(filesAndDirs[0] instanceof Directory)
inside of.then(function(filesAndDirectories){})
at chained to.getFilesAndDirectories()
; - 用
<label>
元素替换<div>
元素作为<input type="file">
的父元素。调整input type="file"
的css
以填充父级可放置容器并将opacity
设置为0
;在input type="file"
的父元素上调整css
以在: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/
解决方案
我想出了以下适用于 Firefox version - 46.0.1
的肮脏解决方法它使用FileReader API检查上传的文件是否是目录。
代码
<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>
相关链接