2010-08-28 34 views
52

我还没有看到任何这样做的例子。这在api规范中是不允许的吗?HTML5是否允许拖放上传文件夹或文件夹树?

我正在寻找一个简单的拖放解决方案来上传整个文件夹的照片树。

+0

同为'INPUT TYPE = file':HTTP://计算器.com/questions/9518335/select-directory-for-html5 -multi-file-input-in-firefox – 2014-08-23 18:52:10

回答

53

它现在可能由于Chrome> = 21

function traverseFileTree(item, path) { 
    path = path || ""; 
    if (item.isFile) { 
    // Get file 
    item.file(function(file) { 
     console.log("File:", path + file.name); 
    }); 
    } else if (item.isDirectory) { 
    // Get folder contents 
    var dirReader = item.createReader(); 
    dirReader.readEntries(function(entries) { 
     for (var i=0; i<entries.length; i++) { 
     traverseFileTree(entries[i], path + item.name + "/"); 
     } 
    }); 
    } 
} 

dropArea.addEventListener("drop", function(event) { 
    event.preventDefault(); 

    var items = event.dataTransfer.items; 
    for (var i=0; i<items.length; i++) { 
    // webkitGetAsEntry is where the magic happens 
    var item = items[i].webkitGetAsEntry(); 
    if (item) { 
     traverseFileTree(item); 
    } 
    } 
}, false); 

更多info:https://protonet.info/blog/html5-experiment-drag-drop-of-folders/

+7

即使2年后,IE和Firefox似乎也不愿意实现这一点。 – 2014-07-03 09:09:59

+0

关于如何在Chrome上使用的问题:http://stackoverflow.com/questions/5826286/how-do-i-use-google-chrome-11s-upload-folder-feature-in-my-own-code?lq = 1 – 2014-08-23 18:52:57

+0

链接不再工作 – frodo2975 2015-02-19 21:16:48

13

this message到HTML 5的邮件列表伊恩·希克森说:

HTML5现在已经在 一次上传多个文件。浏览器可以允许用户 一次选择多个文件,包括跨多个目录的 ;这是一个 位超出了规范的范围。

(另见原feature proposal。) 所以是安全的假设,他认为通过上传拖和下降也超出范围的文件夹。显然,这取决于浏览器为单个文件提供服务。

上传文件夹,也有一些其他的困难,如Lars Gunther描述:

这[...]建议必须有两个 检查(如果可行的话):

  1. 最大尺寸,阻止某人上传几张完整目录 上百张未压缩的原始图片...

  2. 即使省略了accept属性,也进行过滤。 Mac OS元数据 和Windows缩略图等应省略 。所有隐藏的文件和 目录应该默认排除为 。

+0

嗯,我同意第2点...但只有在Web开发人员有方法确定如果他们想要启用隐藏文件的上传 - 因为隐藏文件总是有潜力的可以使用上传的文件夹。特别是如果文件夹是一个完整的文件分割成多个部分,如最终剪切文件可能。 – 2014-08-06 14:57:36

+0

不同意超出范围:这是许多人想要做的事情不兼容的原因,所以应该指定它。 – 2014-08-23 18:50:02

2

HTML5规范并没有说要上传选择的文件夹时,浏览器应该递归上传包含的所有文件。

实际上,在Chrome/Chromium中,您可以上传文件夹,但是当您这样做时,它只会上传一个无意义的4KB文件,它代表目录。像Alfresco一些服务器端的应用程序可以检测到这一点,并警告说,文件夹不能上传用户:

The following cannot be uploaded because they are either folders or are zero bytes in size: undefined

+0

无意义的文件或指向文件的指针? – MoB 2012-08-06 09:02:18

+0

@MoB:也许它确实是某种指针。但是由于实际文件在客户端机器上,当然,服务器机器将无法对该指针进行任何操作。 – 2012-08-06 10:37:26

8

现在你可以上传拖放和输入目录。

<input type='file' webkitdirectory > 

和拖放(对于webkit浏览器)。

处理拖放文件夹。

<div id="dropzone"></div> 
<script> 
var dropzone = document.getElementById('dropzone'); 
dropzone.ondrop = function(e) { 
    var length = e.dataTransfer.items.length; 
    for (var i = 0; i < length; i++) { 
    var entry = e.dataTransfer.items[i].webkitGetAsEntry(); 
    if (entry.isFile) { 
     ... // do whatever you want 
    } else if (entry.isDirectory) { 
     ... // do whatever you want 
    } 
    } 
}; 
</script> 

资源:

http://updates.html5rocks.com/2012/07/Drag-and-drop-a-folder-onto-Chrome-now-available

+1

是否可以在不使用压缩文件夹的情况下进行下载? – user2284570 2015-08-28 09:38:37

1

是否HTML5允许文件夹的拖放上传或文件夹树?

只有Chrome支持此功能。它没有任何牵引力,并可能被删除。

编号:https://developer.mozilla.org/en/docs/Web/API/DirectoryReader#readEntries

+0

哇。从该链接的W3C注释来看,这确实不会继续。假设它没有得到任何牵引力的基础是什么? – bebbi 2016-02-29 12:58:05

+0

@bebbi没有其他浏览器供应商实现它 – basarat 2016-02-29 23:23:22

5

火狐现在支持文件夹上传,2016年11月15日,在v50.0:https://developer.mozilla.org/en-US/Firefox/Releases/50#Files_and_directories

你可以拖放文件夹到Firefox或者您可以浏览并选择本地要上传的文件夹。它还支持嵌套在子文件夹中的文件夹。

这意味着您现在可以使用Chrome,Firefox,Edge或Opera上传文件夹。目前您无法使用Safari或Internet Explorer。

3

此功能将给予您所有的数组承诺丢弃的文件,像<input type="file"/>.files

function getFilesWebkitDataTransferItems(dataTransferItems) { 
    function traverseFileTreePromise(item, path='') { 
    return new Promise(resolve => { 
     if (item.isFile) { 
     item.file(file => { 
      file.filepath = path + file.name //save full path 
      files.push(file) 
      resolve(file) 
     }) 
     } else if (item.isDirectory) { 
     let dirReader = item.createReader() 
     dirReader.readEntries(entries => { 
      let entriesPromises = [] 
      for (let entr of entries) 
      entriesPromises.push(traverseFileTreePromise(entr, path + item.name + "/")) 
      resolve(Promise.all(entriesPromises)) 
     }) 
     } 
    }) 
    } 

    let files = [] 
    return new Promise((resolve, reject) => { 
    let entriesPromises = [] 
    for (let it of dataTransferItems) 
     entriesPromises.push(traverseFileTreePromise(it.webkitGetAsEntry())) 
    Promise.all(entriesPromises) 
     .then(entries => { 
     //console.log(entries) 
     resolve(files) 
     }) 
    }) 
} 

用法:

dropArea.addEventListener("drop", function(event) { 
    event.preventDefault(); 

    var items = event.dataTransfer.items; 
    getFilesFromWebkitDataTransferItems(items) 
    .then(files => { 
     ... 
    }) 
}, false); 
+1

这应该是新接受的答案。它比其他答案要好,因为它在完成时返回一个承诺。但是有一些错误:'函数getFilesWebkitDataTransferItems(dataTransfer)'应该是'function getFilesWebkitDataTransferItems(items)','for(条目的入口)'应该是'for(允许条目的入口)'。 – RoccoB 2017-09-03 03:47:38

相关问题