2016-04-25 223 views
0

我已經使用了一篇文章在SO(我不記得它雖然)解析文件和文件夾在Chrome上,但我不能讓它工作在Firefox上(說實話我沒有嘗試過其他人,但我認爲它不適用於safari)。選擇和刪除文件和/或要解析的文件夾

下面是2個指令,ngDrop和輸入。

angular.module('myApp').directive("ngDrop", function($rootScope) { 
    var link = function($scope, elements, attr, ngModel) { 

     var parseInput = function(event) { 
      var list = []; 
      $scope.count = 0; 

      var toParse = []; 
      for (var i = 0; i < event.dataTransfer.items.length; i++) { 
       toParse.push(event.dataTransfer.items[i].webkitGetAsEntry()); 
      } 

      var traverse_directory = function(entry) { 
       var reader = entry.createReader(); 
       // Resolved when the entire directory is traversed 
       return new Promise(function executer(resolve_directory) { 
        var iteration_attempts = []; 
        (function read_entries() { 
         // According to the FileSystem API spec, readEntries() must be called until 
         // it calls the callback with an empty array. Seriously?? 
         reader.readEntries(function(entries) { 
          if (!entries.length) { 
           // Done iterating this particular directory 
           resolve_directory(Promise.all(iteration_attempts)); 
          } else { 
           // Add a list of promises for each directory entry. If the entry is itself 
           // a directory, then that promise won't resolve until it is fully traversed. 
           iteration_attempts.push(Promise.all(entries.map(function(entry) { 
            if (entry.isFile) { 
             list.push(entry); 
             return entry; 
            } else { 
             return traverse_directory(entry); 
            } 
           }))); 
           // Try calling readEntries() again for the same dir, according to spec 
           read_entries(); 
          } 
         }); 
        })(); 
       }); 
      }; 

      var updateNgModel = function() { 
       var files = [], count = 0; 
       for (var i = 0; i < list.length; i++) { 
        list[i].file(function(file) { 
         files.push(file); 
         count++; 
         if (count === list.length) { 
          ngModel.$setViewValue(files); 
         } 
        }); 
       } 
      }; 

      for (var j = 0; j < toParse.length; j++) { 
       if (toParse[j].isFile) { 
        list.push(toParse[j]); 
       } else if (toParse[j].isDirectory) { 
        $scope.count++; 
        traverse_directory(toParse[j]).then(function() { 
         $scope.count--; 
         if ($scope.count == 0) { 
          updateNgModel(); 
         } 
        }); 
       } 
      } 
      if ($scope.count == 0) { 
       updateNgModel(); 
      } 
     } 

     elements[0].ondrop = function(event) { 
      event.stopPropagation(); 
      event.preventDefault(); 

      // ... styling 

      parseInput(event); 
     }; 

     elements[0].ondragover = function(event) { 
      event.preventDefault(); 
     }; 
    }; 

    return { 
     restrict: 'A', 
     require:"^ngModel", 
     link: link 
    }; 
}); 

// select file on input 
angular.module('myApp').directive("input", function($rootScope) { 
    var link = function($scope, elements, attr, ngModel) { 
     if (attr.type && attr.type.toLowerCase() === 'file') { 
      elements[0].onchange = function(event) { 
       var list = event.__files_ || (event.target && event.target.files); 
       var files = []; 
       for (var i = 0; i < list.length; i++) { 
        files.push(list[i]); 
       } 
       ngModel.$setViewValue(files); 
      }; 
     } 
    }; 

    return { 
     restrict: 'E', 
     require:"^ngModel", 
     link: link 
    }; 
}); 

關於實施,這是我如何使用它們:

<div class="dropzone" ng-model="files" ng-drop> 
    <input type="file" ng-model="files" webkitdirectory multiple> 
    <h2><i class="fa fa-upload"></i> Drop Images Here !</h2> 
    <div>Or just click to select files.</div> 
</div> 

該指令的兩個主要用來填補ngModel。

Here's a plunkr

現在,當我拖/下降FF:TypeError: event.dataTransfer.items is undefined 當我選擇:TypeError: list is null

我可以改變,以得到它的兩個Chrome和Firefox,爲什麼工作不,還其他瀏覽器在同一時間?

+0

不能確定'angularjs'部分; [這個答案](http://stackoverflow.com/a/36828612)應該解決閱讀目錄和問題的文件部分。 – guest271314

回答

0

我可以改變讓它在Chrome和Firefox瀏覽器

注意,火狐目前不支持directory屬性在input type="file"元素來讀取上傳的文件夾; .webkitGetAsEntry()不是Firefox支持的方法。

嘗試使用<input type="file">multiple,webkitdirectory屬性設置; <input type="radio">供用戶選擇文件夾或文件上傳以在input type="file"元素上切換webkitdirectory屬性。 Can't select files when webkitdirectory is present on <input type="file" />Allow chrome to select both/either directory or files

window.onload = function() { 
 
    var results = document.getElementById("results"); 
 
    var dropped = document.getElementById("filesDropped"); 
 
    var file = document.getElementById("file"); 
 
    var files = document.getElementById("files"); 
 
    var folder = document.getElementById("folder"); 
 
    document.getElementById("type").onchange = function(e) { 
 
    file[(files.checked ? "remove" : "set") 
 
     + "Attribute"]("webkitdirectory", true) 
 
    } 
 

 
    file.onchange = function(e) { 
 
    results.innerHTML = ""; 
 
    e.preventDefault(); 
 
    e.stopImmediatePropagation(); 
 
    var files = e.target.files; 
 
    dropped.innerHTML = files.length; 
 
    for (var i = 0; i < files.length; i++) { 
 
     if (/image/.test(files[i].type)) { 
 
     (function(j) { 
 
      var img = new Image; 
 
      img.onload = function() { 
 
      console.log(files[j]); 
 
      var figure = document.createElement("figure"); 
 
      var figcaption = document.createElement("figcaption"); 
 
      figcaption.innerHTML = files[j].name; 
 
      figure.appendChild(figcaption); 
 
      figure.appendChild(img); 
 
      results.appendChild(figure); 
 
      URL.revokeObjectURL(url); 
 
      } 
 
      var url = URL.createObjectURL(files[j]); 
 
      img.src = url; 
 
     }(i)) 
 
     } else { 
 
     console.log(files[i].type, files[i]) 
 
     } 
 
    } 
 
    results.style.width = width; 
 
    } 
 
}
#dropzone { 
 
    padding: 0px; 
 
    margin: 0px; 
 
    width: 400px; 
 
    height: 300px; 
 
    border: 2px dotted green; 
 
} 
 
#dropzone:hover { 
 
    border: 4px dotted blue; 
 
} 
 
#dropzone input { 
 
    width: 400px !important; 
 
    height: 300px !important; 
 
    opacity: 0; 
 
} 
 
#results { 
 
    position: relative; 
 
    display: block; 
 
    width: auto; 
 
    min-height: 50px; 
 
} 
 
#filesDropped:after { 
 
    content: " Files dropped:"; 
 
} 
 
figure, 
 
figcaption { 
 
    display: block; 
 
    position: relative; 
 
    width: 100%; 
 
}
<span id="filesDropped"></span> 
 
<div id="results"></div> 
 
<br> 
 
<span id="type">Drop files <input id="files" name="type" type="radio"> folder <input checked id="folder" name="type" type="radio">:</span> 
 
<div id="dropzone"> 
 
    <input id="file" type="file" multiple webkitdirectory/> 
 
</div>

+0

我已經這麼做了。我想沒有比等待Firefox支持目錄支持更好的解決方案了。我希望能做一些調整,讓我能夠解析掉一個丟失的目錄。不管怎樣,謝謝。 – Romain

+0

@RomainFournereau每晚45+支持'.getFilesAndDirectories()';請參閱http://superuser.com/questions/909112/does-firefox-support-folder-upload – guest271314

+0

但是FF 46穩定版不支持它嗎? – Romain

0

每晚45+支持目錄上傳。見Does Firefox support folder upload?

window.onload = function() { 
 
    document.querySelector("input").onchange = function(e) { 
 

 
    var uploadFile = function(file, path) { 
 
     // handle file uploading 
 
     console.log(file, path) 
 
    }; 
 

 
    var iterateFilesAndDirs = function(filesAndDirs, path) { 
 
     for (var i = 0; i < filesAndDirs.length; i++) { 
 
     if (typeof filesAndDirs[i].getFilesAndDirectories === "function") { 
 
      var path = filesAndDirs[i].path; 
 

 
      // this recursion enables deep traversal of directories 
 
      filesAndDirs[i].getFilesAndDirectories().then(function(subFilesAndDirs) { 
 
      // iterate through files and directories in sub-directory 
 
      iterateFilesAndDirs(subFilesAndDirs, path); 
 
      }); 
 
     } else { 
 
      uploadFile(filesAndDirs[i], path); 
 
     } 
 
     } 
 
    }; 
 
    if ("getFilesAndDirectories" in e.target) { 
 
     e.target.getFilesAndDirectories() 
 
     .then(function(filesAndDirs) { 
 
      iterateFilesAndDirs(filesAndDirs, "/"); 
 
     }) 
 
    } else { 
 
     // do webkit stuff 
 
    } 
 
    } 
 
}
<input type="file" webkitdirectory allowdirs directory />

plnkr http://plnkr.co/edit/DSUeZiW4JjvxmRrFnqN0?p=preview

相關問題