我使用type =" file"创建了一个输入元素,其中包含多个,webkit目录,allowdirs和目录属性。
然后我添加了一个"更改"事件处理程序,当我选择要上传的文件目录时,它就可以工作。
但是,如果我不小心选择了一个空目录,我就不会收到更改事件。是否还有其他事件可用于检测是否已选择空目录?
我希望能够告诉用户所选目录是空的并尝试选择另一个目录。现在我无法检测到用户已经做了任何事情,并且用户没有被告知为什么他们的选择没有做任何事情。
据报道这是一个错误:
https://bugs.chromium.org/p/chromium/issues/detail?id=360412
但我想知道是否有解决方法。
答案 0 :(得分:0)
您可以使用Directory
构造函数在File
事件处迭代drop
和Promise
个实例,调度函数调用自身,将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;