现要求能在浏览器上直接拖放一个文件夹实现批量上传
Html5规范还不支持
但是目前chrome >= 21 浏览器支持
现在文件的拖放上传采用的是
jquery-filedrop.js
https://github.com/weixiyen/jquery-filedrop
这个不支持文件夹
我把这个做了改进,可以支持文件夹。
原先代码:
function drop(e) { if( opts.drop.call(this, e) === false ) return false; files = e.dataTransfer.files; if (files === null || files === undefined || files.length === 0) { opts.error(errors[0]); return false; } files_count = files.length; upload(); e.preventDefault(); return false; }
改进如下:
function drop(e) { if( opts.drop.call(this, e) === false ) return false; function walkFileSystem(directory, callback, error) { if (!callback.pending) { callback.pending = 0; } if (!callback.files) { callback.files = []; } callback.pending++; var reader = directory.createReader(), relativePath = directory.fullPath.replace(/^\//, '').replace(/(.+?)\/?$/, '$1/'); reader.readEntries(function(entries) { callback.pending--; $.each(entries, function(index, entry) { if (entry.isFile) { callback.pending++; entry.file(function(File) { File.path = encodeURIComponent(relativePath); callback.files.push(File); if (--callback.pending === 0) { callback(callback.files); } }, error); } else { walkFileSystem(entry, callback, error); } }); if (callback.pending === 0) { callback(callback.files); } }, error); } var items = e.dataTransfer.items || [], firstEntry; if (items[0] && items[0].webkitGetAsEntry && (firstEntry = items[0].webkitGetAsEntry())) { // Experimental way of uploading entire folders (only supported by chrome >= 21) walkFileSystem(firstEntry.filesystem.root, function(allfiles) { files = allfiles; files_count = files.length; upload(); }, function() { // Fallback to old way when error happens files = e.dataTransfer.files; files_count = files.length; upload(); }); } else { files = e.dataTransfer.files; files_count = files.length; upload(); } e.preventDefault(); return false; }
以上改进点说明:
如果浏览器支持文件夹拖放,判断类型,如果是文件夹就递归读取文件夹目录树,
找到所有文件,最后在上传。
怎样做到按目录树保存文件呢?
其实递归读取文件夹时,我给文件赋值了path值,就是相对路径,
这样服务端就可以根据这个path,实现按目录树保存了。
其他地方的修改点就不一一列出了,附上修改后的完整代码。