Вопрос

Недавно я внес некоторый код Moodle, который использует некоторые возможности HTML5, чтобы позволить загружать файлы в формах через перетаскивание с рабочего стола (основная часть кода здесь: https://github.com/moodle/moodle/blob/master/lib/form/dndupload.js для справки).

Это работает хорошо, за исключением случаев, когда пользователь затягивает а папка / каталог вместо реального файла. Затем мусор загружается на сервер, но с именем файла, соответствующим папке.

Я ищу легкий и надежный способ обнаруживать присутствие папка в FILLIST Объект, поэтому я могу пропустить его (и, вероятно, вернуть дружественное сообщение об ошибке).

Я просмотрел документацию по MDN, а также более общий веб -поиск, но ничего не обнаружил. Я также просматривал данные в инструментах разработчика Chrome, и кажется, что 'тип' объекта файла постоянно устанавливается на "" для папок. Тем не менее, я не совсем уверен, что это самый надежный метод обнаружения кросс-браузера.

У кого -нибудь есть лучшие предложения?

Это было полезно?

Решение

Вы не можете полагаться на file.type. Анкет Файл без расширения будет иметь тип "". Анкет Сохраните текстовый файл с помощью .jpg расширение и загрузите его в элемент управления файлом, и его тип будет отображаться как image/jpeg. Анкет И папка под названием «somefolder.jpg» также будет иметь свой тип как image/jpeg.

Попробуйте прочитать файл с помощью FileReader. Анкет Если втащен каталог, FileReader поднимет error мероприятие:

var reader = new FileReader();
reader.onload = function (e) {
    // it's a file
};
reader.onerror = function (e) {
    // it's a directory
};
reader.readAsText(file);

К счастью, в IE11, когда каталог сброшен, e.dataTransfer.files Коллекция пуста.

Chrome раскрывает дополнительную собственность в e.dataTransfer называется items содержащий коллекцию DataTransferItem объекты. На каждом из этих объектов вы можете позвонить item.webkitGetAsEntry(), который возвращает Entry объект. А Entry У объекта есть свойства isDirectory а также isFile:

// Chrome only
if (e.dataTransfer.items && e.dataTransfer.items.length) {
   [].forEach.call(e.dataTransfer.items, function(item) {
      var entry = item.webkitGetAsEntry();
      if (entry && entry.isFile) {
         var file = item.getAsFile(); // same as object in e.dataTransfer.files[]
         // do something with the file
      }
   }
}

Интересно, что в моих экспериментах каждая папка, на которую я смотрел File.size % 4096 как ноль. Однако, конечно, некоторые файлы также будут иметь это. File.size не является надежным индикатором того, является ли файл на самом деле папкой.

Другие советы

Я также столкнулся с этой проблемой, и ниже - мое решение. По сути, я взял на себя два якового подхода:

(1) Проверьте, является ли размер объекта файла большим, и считайте его подлинным файлом, если он превышает 1 МБ (я предполагаю, что сами папки никогда не бывают такими большими).(2) Если объект файла меньше 1 МБ, то я прочитал его, используя метод «readasarraybuffer» FileReader. Успешное чтение вызов «Onload», и я считаю, что это указывает на то, что объект файла является подлинным файлом. Неудачный чтение Call «Onerror», и я считаю это каталогом. Вот код:

var isLikelyFile = null;
if (f.size > 1048576){ isLikelyFile = false; }
else{
    var reader = new FileReader();
    reader.onload = function (result) { isLikelyFile = true; };
    reader.onerror = function(){ isLikelyFile = false; };
    reader.readAsArrayBuffer(f);
}
//wait for reader to finish : should be quick as file size is < 1MB ;-)
var interval = setInterval(function() {
    if (isLikelyFile != null){
        clearInterval(interval);
        console.log('finished checking File object. isLikelyFile = ' + isLikelyFile);
    }
}, 100);

Я проверил это в FF 26, Chrome 31, и Safari 6 и три браузера называют «Onerror» при попытке чтения каталогов. Дайте мне знать, если кто -то может подумать о случае использования, когда это не удается.

Я предлагаю звонить FileReader.readAsBinaryString на File объект. В Firefox это поднимет исключение, когда File это Directory. Анкет Я делаю это только в случае File соответствует условиям, предложенным Gilly3.

Пожалуйста, смотрите мой блог на http://hs2n.wordpress.com/2012/08/13/deting-folders-in-html-prop-area/ Больше подробностей.

Кроме того, версия 21 Google Chrome теперь поддерживает папки сбрасывания. Вы можете легко проверить, являются ли папки сброшенных элементов, а также прочитать их содержимое.

К сожалению, у меня нет (клиентского) решения для старых хромированных версий.

Еще одно примечание заключается в том, что тип «» для любого файла, который имеет неизвестное расширение. Попробуйте загрузить файл с именем test.blah, и тип будет пустым. И ... попробуйте перетащить и сбрасывать папку с именем test.jpg - тип будет установлен на «Image/jpeg». Чтобы быть на 100% правильным, вы не можете зависеть только от типа (или, если вообще, на самом деле).

В моем тестировании папки всегда имели размер 0 (на FF и Chrome на 64-битной Windows 7 и Mine Mint (по существу Ubunt В нашей среде. Мы также не хотим, чтобы файлы 0 -байтовых загружались либо, если это 0 байтов, сообщение возвращается как «пропущенные - 0 байт (или папку)»

К вашему сведению, этот пост сообщит вам, как использовать API Datatransfer в Chrome для обнаружения типа файла: http://updates.html5rocks.com/2012/07/drag-and-prop-a-folder-onto-chrome-now-vailable

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top