咱们在不少的项目场景当中,都会碰到须要上传文件的状况,相信大部分前端仔都对上传的机制熟稔于心了,无非就是表单上传,拖拽上传等等,基本都是玩的溜溜的了。而今天咱们讲的是其中鲜为人知的一块内容---经过拖拽的方式来上传整个文件夹的内容~前端
咱们经过
<input type='file' multiple>
只能实现多文件的上传,可是对于文件夹的上传依旧是一筹莫展web
既然讲的是拖拽上传文件夹,那么咱们天然从咱们的拖拽的事件对象讲起了。数组
咱们来看一下MDN对dataTransfer
对象的描述: DataTransfer
被用于承载拖拽和拖放时的数据,它能够承载多个数据项。服务器
注意:当咱们的拖放动做解释并完成回调函数以后,dataTransfer中的数据项就会被清理回收,若是咱们在拖拽的过程须要作一些额外的判断或者在回调外进行操做时,须要强引用这些数据项的内容,防止其被垃圾回收机制给回收掉。markdown
DataTransfer.files
: 这个属性就是一个文件伪数组,用来存储拖拽对象的文件属性,若是拖拽的不是文件,那么这个数组为空。 DataTransfer.items
该属性就是咱们此次的关注重点,数据选项,为何这么说,由于这个数据项支持文件的读取,而其特有的文件的属性以及最为重要的entry
对象是咱们实现文件夹上传的重中之重。 DataTransfer.getData/DataTransfer.setData
这个API是DataTransfer
比较重要的一个属性,他能够自由的设置和读取属性。着就给咱们进行组件的拖拽创造了无限的可能。通常咱们都是经过源组件的dragstart
事件调用DataTransfer.setData()
传入数据,而后在目的组件当中经过DataTransfer.getData()
来获取数据进行相关操做。app
注意:这两个API没法直接传入对象,建议经过JSON序列化和反序列化的手段来进行对象的传递。ide
因为DataTransfer
含有大量额外的接口以及属性咱们就不展开讨论,有兴趣的童鞋能够去MDN自行阅读,说不定就能找到知足你业务需求的接口哦~函数
DataTransfer.items
是一个DataTransferItemList
对象,这个对象一样的也是一个伪数组,它含有length
属性。每个数组成员都是一个DataTransferItem
对象。咱们的拖拽文件夹操做就是须要依靠这个对象来实现的。ui
咱们接着着重来看这个对象。lua
这个API就是咱们引出下一个关键对象的入口,这个是一个非标准的API看他的函数名咱们也能够知道是支持webkit的一个API。这个API是干什么的?咱们来看一下MDN官方的解释(本人翻译,建议能够看原版英文): 若是DataTransferItem
承载的是一个文件数据,那么咱们能够用调用该API来建立一个FileSystemFileEntry
或者FileSystemDirectoryEntry
对象。望文生义,很显然咱们能够经过这两个对象来区分咱们拖拽的是文件仍是文件夹。这两个对象都是经过FileSystemEntry
接口扩展的 这个两个对象同时都拥有isFile
和isDirectory
属性用来描述这个对象是文件仍是文件夹。咱们能够判断这两个属性从而进一步进行操做。 FileSystemEntry.fullPath
这个属性是用来保存彻底路径的,根目录就是最初拖拽的文件夹路径。咱们后续上传服务器就会用到这个属性。
注意:接下来大部分的API都是非标准的API,在后续可能有变化,若是须要在公司业务使用,建议标注清楚使用事项和注意事项。
FileSystemFileEntry.file()
函数用来实际读取文件内容,该函数能够注册两个回调函数,一个成功回调,一个失败错误回调。在成功回调中,会把真正的file对象传入进来,而后后面作什么事,就不言而喻了吧~ FileSystemDirectoryEntry.createReader()
这个API用来实现建立一个FileSystemDirectoryReader
API用来读取文件夹中的FileSystemFileEntry
对象了。和FileSystemFileEntry.file()
用法同样,也是在FileSystemDirectoryReader.readEntries
中注册成功回调,而后在回调中传入实际的entries数组。到了这里咱们差很少也就了解了整个的相关API的状况了,那么接下来就是递归遍历文件夹的工做了,代码就不写了逻辑也不是特别难。到此结束