2016-04-25 5 views
0

Я использовал часть из сообщения здесь, на SO (я не могу вспомнить об этом), чтобы анализировать файлы и папки в Chrome, но я не могу заставить его работать на Firefox (и, честно говоря, я не пробовал это на других, хотя я думаю, что он тоже не работает на сафари).Выбор и удаление файлов и/или папок для разбора

Вот 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"> для выбора пользователем или загрузки файлов для переключения webkitdirectory атрибут на input type="file" элемент. 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 stable еще не поддерживает его? – Romain

0

Nightly 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