[关闭]
@bornkiller 2014-08-30T23:33:52.000000Z 字数 3358 阅读 3366

FileSystem

javascript


前言

文件拖动上传,对于个别应用场景十分有效,实现起来也并不难。参见
“浏览器图片预览 --http://blog.segmentfault.com/bornkiller/1190000000428572"。
现在更进一步,做到文件夹拖动。以下内容全基于chrome 36 版本测试成功。

参考资料

FileSystem API

API 被分为以下不同的主题:
读取和处理文件:File/Blob、FileList、FileReader
创建和写入:BlobBuilder、FileWriter
目录和文件系统访问:DirectoryReader、FileEntry/DirectoryEntry

启用文件存储系统

  1. var requestFileSystem = window.requestFileSystem ?
  2. window.requestFileSystem:
  3. window.webkitRequestFileSystem;
  4. // success 回调函数
  5. var onInitFS = function(fs) {};
  6. // error 回调函数
  7. var onInitFE = function(fe) {};
  8. requestFileSystem(window.TEMPORARY, 10*1024*1024, onInitFS, onInitError);

文件夹拖动

拦截默认行为,并阻止冒泡

  1. window.addEventListener('load', function(evt) {
  2. document.addEventListener('drop', prevent);
  3. document.addEventListener('dragenter', prevent);
  4. document.addEventListener('dragleave', prevent);
  5. document.addEventListener('dragover', prevent);
  6. });
  7. function prevent(e){
  8. e.stopPropagation();
  9. e.preventDefault();
  10. }

获得FileEntry/DirectoryEntry

  1. document.addEventListener('drop',entryResolve);
  2. function entryResolve(e){
  3. var items = e.dataTransfer.items;
  4. // 多文件/文件夹拖动时,items.length即为拖入文件/文件夹数量
  5. var itemsCount = items.length;
  6. // 获取文件/文件夹Entry对象
  7. var entries = [];
  8. for (var i=0; i<itemsCount; i++) {
  9. entries.push(items[i].webkitGetAsEntry());
  10. }
  11. }

处理FileEntry/DirectoryEntry

每个Entry对象具备isDirectory, isFile属性,判定目标为文件或是文件夹。具体接口可以自行查阅

  1. entries.forEach(function(entry, key) {
  2. if(entry.isDirectory && !entry.isFile) {
  3. // entry is DirectoryEntry here
  4. }else if(!entry.isDirectory && entry.isFile) {
  5. // entry is FileEntry here
  6. }else{
  7. return false;
  8. }
  9. })

文件夹遍历

  1. function readDir(directoryEntry, readDirCallback) {
  2. // 判定参数类型是否匹配
  3. if (!directoryEntry.isDirectory || !typeof value === 'function') {
  4. return false;
  5. }
  6. var fileEntriesContainer = [];
  7. // 创建目录遍历器 dirReader
  8. var dirReader = directoryEntry.createReader();
  9. // 遍历目录,由于无法一次性返回全部,所以需要递归调用,直到返回结果为空,执行回调函数。
  10. var readEntries = function() {
  11. dirReader.readEntries (function(results) {
  12. if (!results.length) {
  13. readDirCallback(fileEntriesContainer);
  14. } else {
  15. fileEntriesContainer = fileEntriesContainer.concat(toArray(results));
  16. readEntries();
  17. }
  18. }, errorHandler);
  19. };
  20. readEntries();
  21. }
  1. function readDirectoryEntry(directoryEntry) {
  2. return Q.Promise(function(resolve, reject) {
  3. if(directoryEntry.isDirectory) {
  4. resolve(true);
  5. } else {
  6. reject(false);
  7. }
  8. }).then(function() {
  9. return readDirectory(directoryEntry);
  10. })
  11. };
  12. // 返回值为promise,传递值为目录下所有的entry对象组成的数组。
  13. function readDirectory(directoryEntry) {
  14. var defer = Q.defer();
  15. var fileEntriesContainer = [];
  16. var dirReader = directoryEntry.createReader();
  17. // Call the reader.readEntries() until no more results are returned.
  18. var readEntries = function() {
  19. dirReader.readEntries(function(results) {
  20. if (!results.length) {
  21. defer.resolve(fileEntriesContainer);
  22. } else {
  23. fileEntriesContainer = fileEntriesContainer.concat(toArray(results));
  24. readEntries();
  25. }
  26. }, function(err) {
  27. defer.reject(err.message);
  28. });
  29. };
  30. readEntries();
  31. return defer.promise;
  32. }

FileEntry 转换 File 及文件操作

  1. // 通过file函数即可获得File 对象
  2. // File 对象处理请自行参阅 FileReader
  3. entry.file(function(file){
  4. var fileReader = new FileReader();
  5. fileReader.readAsText(file);
  6. fileReader.addEventListener('load', function(){
  7. console.log(this.result);
  8. })
  9. })

交流

QQ : 491229492
注明交流即可

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注