如何使用更改和删除事件上传和列出Firefox和chrome / chrome上的目录 [英] How to upload and list directories at firefox and chrome/chromium using change and drop events
问题描述
< input type =file>
元素中选择目录或目录或者删除元素时,如何按照出现的顺序列出所有目录和文件在firefox和chrome / chrome的实际目录中,在所有上传的目录都被迭代时执行文件的任务?你可以将 webkitdirectory
和 allowdirs
属性设置为< input type =file>
元素;将更改
, drop
事件到< input type =file>
元素;在mozilla上使用 .getFilesAndDirectories()
.createReader()
, .readEntries() / code>在
webkit
, Array.prototype.reduce()
,承诺
,递归。
注意在firefox drop
事件不将选择列为目录
,但是文件
对象具有大小
0
,因此在firefox下删除目录不提供丢弃文件夹的表示,即使在 event.dataTransfer.getFilesAndDirectories()
被使用的情况下。当 allowdirs
属性设置时,firefox还提供两个输入元素;第一个元素允许单个文件上传,第二个元素允许目录上传。铬/铬提供单个< 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;
内容:将文件或文件夹放在这里!\aOr点击选择文件夹;
position:relative;
剩余:0%;
顶部:-75px;
文本对齐:中心;
}
.drag {
border:5px点绿色;
背景颜色:黄色;
}
#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;
颜色:海军;
}
< / style>
< / head>
< body>
< label id =dropAreaclass =area>
< input id =filetype =file目录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);
函数dragHandler(event){
event.stopPropagation();
event.preventDefault();
dropArea.className =area drag;
}
函数filesDroped(event){
var webkitResult = [];
var mozResult = [];
var files;
console.log(event);
event.stopPropagation();
event.preventDefault();
dropArea.className =area;
// do mozilla stuff
// TODO调整,调用`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()条目)
.then(function(dir){
return dir
})
})
},Promise.resolve())
。 (function(items){
var dir = items.filter(function(folder){
return folder instanceof Directory
});
var files = items.filter(function文件){
返回文件instanceof文件
});
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
})
}
}
})
};
函数handleEntries(entry){
let file =webkitGetAsEntryin 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)
}))然后(resolve)
})
}
})
函数webkitReadDirectories(条目,回调,解析,条目){
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())
})然后(解析)。
}
}
// TODO:处理mozilla目录,删除并列出没有
的其他目录//在html中创建嵌套列表,其中不同的目录选择或删除
函数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>
目录名称:$ {entry.name}< br>
路径:$ {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>
名称:$ {file.name}< / br>
大小:$ {file.size} bytes< / br>
类型:$ {file.type}< / br>
修改日期:$ {file.lastModifiedDate}< br>
全路径:$ {path}
< / li>`;
var currentPath = path.split(/)。filter(Boolean);
currentPath.pop();
var attached = 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}`)
added = true;
break;
}
}
if(!attached){
curr [curr.length - 1] .innerHTML + =`$ {filesInfo}`;
}
}
console.log(`read $ {file.name},size:$ {file.size},path:$ {path}`);
webkitResult.push(file);
return Promise.resolve(webkitResult)
};
函数processFiles(files){
Promise.all([]。map.call(files,function(file,index){
return handleEntries(file,index)然后(handleFile)
}))
.then(function(){
console.log(complete,webkitResult)
})
.catch (err){
alert(err.message);
})
}
if(getFilesAndDirectoriesin 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);
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
+在firefox的drop事件,上传文件夹在'选择文件夹...'输入);
}
}
}
})catch(function(err){
alert(err)
})
}
//做webkit的东西
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>
plnkr http://plnkr.co/edit/ff5vmuuIMzSapu6MiUJ3?p=preview
Both mozilla and webkit browsers now allow directory upload. When directory or directories are selected at <input type="file">
element or dropped at an element, how to list all directories and files in the order which they appear in actual directory at both firefox and chrome/chromium, and perform tasks on files when all uploaded directories have been iterated?
You can set webkitdirectory
and allowdirs
attributes at <input type="file">
element; attach change
, drop
events to <input type="file">
element; use .getFilesAndDirectories()
at mozilla, .createReader()
, .readEntries()
at webkit
, Array.prototype.reduce()
, Promise
, recursion.
Note at firefox drop
event does not list selection as a Directory
, but a File
object having size
0
, thus dropping directory at firefox does not provide representation of dropped folder, even where event.dataTransfer.getFilesAndDirectories()
is utilized. firefox also provides two input elements when allowdirs
attribute is set; the first element allows single file uploads, the second element allows directory upload. chrome/chromium provide single <input type="file">
element where only single or multiple directories can be selected, not single file.
At directories containing both files and directories, directories are read first.
<!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>
plnkr http://plnkr.co/edit/ff5vmuuIMzSapu6MiUJ3?p=preview
这篇关于如何使用更改和删除事件上传和列出Firefox和chrome / chrome上的目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!