如何使用更改和删除事件上传和列出Firefox和chrome / chrome上的目录 [英] How to upload and list directories at firefox and chrome/chromium using change and drop events

查看:138
本文介绍了如何使用更改和删除事件上传和列出Firefox和chrome / chrome上的目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

mozilla和webkit浏览器现在允许目录上传。当在< 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆