Позволяет ли HTML5 перетаскивать папки или дерево папок?


Я не видел никаких примеров этого. Это не разрешено в спецификации api?

Я ищу простое решение для перетаскивания для загрузки всего дерева папок фотографий.

8 53

8 ответов:

теперь это возможно, благодаря Chrome >= 21.

function traverseFileTree(item, path) {
  path = path || "";
  if (item.isFile) {
    // Get file
    item.file(function(file) {
      console.log("File:", path + file.name);
    });
  } else if (item.isDirectory) {
    // Get folder contents
    var dirReader = item.createReader();
    dirReader.readEntries(function(entries) {
      for (var i=0; i<entries.length; i++) {
        traverseFileTree(entries[i], path + item.name + "/");
      }
    });
  }
}

dropArea.addEventListener("drop", function(event) {
  event.preventDefault();

  var items = event.dataTransfer.items;
  for (var i=0; i<items.length; i++) {
    // webkitGetAsEntry is where the magic happens
    var item = items[i].webkitGetAsEntry();
    if (item) {
      traverseFileTree(item);
    }
  }
}, false);

дополнительная информация:https://protonet.info/blog/html5-experiment-drag-drop-of-folders/

на этой в список рассылки HTML 5 Ян Хиксон говорит:

HTML5 теперь должен загружать много файлов по адресу однажды. Браузеры могут позволить пользователям выберите несколько файлов одновременно, в том числе в нескольких каталогах; вот это немного выходит за рамки спецификации.

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

загрузка папок также будет иметь некоторые другие трудности, как описано Ларс Гунтер:

этого [...] предложение должны есть два проверяет (если это вообще выполнимо):

  1. максимальный размер, чтобы остановить кого-то от загрузки полного каталога из нескольких сотни несжатых необработанных изображений...

  2. фильтрация, даже если принять атрибут опущен. Метаданные Mac OS и миниатюры Windows и т. д. должны быть опущено. Все скрытые файлы и каталоги должны быть по умолчанию исключенный.

теперь вы можете загружать каталоги с помощью перетаскивания и ввода.

<input type='file' webkitdirectory >

и для перетаскивания (для браузеров webkit).

обработка перетаскивания папок.

<div id="dropzone"></div>
<script>
var dropzone = document.getElementById('dropzone');
dropzone.ondrop = function(e) {
  var length = e.dataTransfer.items.length;
  for (var i = 0; i < length; i++) {
    var entry = e.dataTransfer.items[i].webkitGetAsEntry();
    if (entry.isFile) {
      ... // do whatever you want
    } else if (entry.isDirectory) {
      ... // do whatever you want
    }
  }
};
</script>

ресурсы:

http://updates.html5rocks.com/2012/07/Drag-and-drop-a-folder-onto-Chrome-now-available

Firefox теперь поддерживает загрузку папок, по состоянию на 15 ноября 2016 года, в v50. 0: https://developer.mozilla.org/en-US/Firefox/Releases/50#Files_and_directories

вы можете перетаскивать папки в Firefox или вы можете просматривать и выбирать локальную папку для загрузки. Он также поддерживает папки, вложенные в подпапки.

Это означает, что теперь вы можете использовать Chrome, Firefox, Edge или Opera для загрузки папок. Вы не можете использовать Safari или Internet Explorer на подарок.

эта функция даст вам массив всех удаленных файлов, как <input type="file"/>.files:

function getFilesWebkitDataTransferItems(dataTransferItems) {
  function traverseFileTreePromise(item, path='') {
    return new Promise( resolve => {
      if (item.isFile) {
        item.file(file => {
          file.filepath = path + file.name //save full path
          files.push(file)
          resolve(file)
        })
      } else if (item.isDirectory) {
        let dirReader = item.createReader()
        dirReader.readEntries(entries => {
          let entriesPromises = []
          for (let entr of entries)
            entriesPromises.push(traverseFileTreePromise(entr, path + item.name + "/"))
          resolve(Promise.all(entriesPromises))
        })
      }
    })
  }

  let files = []
  return new Promise((resolve, reject) => {
    let entriesPromises = []
    for (let it of dataTransferItems)
      entriesPromises.push(traverseFileTreePromise(it.webkitGetAsEntry()))
    Promise.all(entriesPromises)
      .then(entries => {
        //console.log(entries)
        resolve(files)
      })
  })
}

использование:

dropArea.addEventListener("drop", function(event) {
  event.preventDefault();

  var items = event.dataTransfer.items;
  getFilesFromWebkitDataTransferItems(items)
    .then(files => {
      ...
    })
}, false);

спецификация HTML5 не говорит, что при выборе папки для загрузки браузер должен рекурсивно загружать все содержащиеся файлы.

на самом деле, в Chrome/Chromium вы можете загрузить папку, но когда вы это делаете, она просто загружает бессмысленный файл 4KB, который представляет каталог. Некоторые серверные приложения, такие как на свежем воздухе может обнаружить это, и предупредить пользователя, что папки не могут быть загружены:

The following cannot be uploaded because they are either folders or are zero bytes in size: undefined

позволяет ли HTML5 перетаскивать загрузку папок или дерева папок?

только Chrome поддерживает эту функцию. Он не имеет никакой тяги и, вероятно, будет удален.

Ref:https://developer.mozilla.org/en/docs/Web/API/DirectoryReader#readEntries

вот полный пример того, как использовать записи файлов и каталогов API:

var dropzone = document.getElementById("dropzone");
var listing = document.getElementById("listing");

function scanAndLogFiles(item, container) {
  var elem = document.createElement("li");
  elem.innerHTML = item.name;
  container.appendChild(elem);

  if (item.isDirectory) {
    var directoryReader = item.createReader();
    var directoryContainer = document.createElement("ul");
    container.appendChild(directoryContainer);

    directoryReader.readEntries(function(entries) {
      entries.forEach(function(entry) {
        scanAndLogFiles(entry, directoryContainer);
      });
    });
  }
}

dropzone.addEventListener(
  "dragover",
  function(event) {
    event.preventDefault();
  },
  false
);

dropzone.addEventListener(
  "drop",
  function(event) {
    var items = event.dataTransfer.items;

    event.preventDefault();
    listing.innerHTML = "";

    for (var i = 0; i < items.length; i++) {
      var item = items[i].webkitGetAsEntry();

      if (item) {
        scanAndLogFiles(item, listing);
      }
    }
  },
  false
);
body {
  font: 14px "Arial", sans-serif;
}

#dropzone {
  text-align: center;
  width: 300px;
  height: 100px;
  margin: 10px;
  padding: 10px;
  border: 4px dashed red;
  border-radius: 10px;
}

#boxtitle {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  color: black;
  font: bold 2em "Arial", sans-serif;
  width: 300px;
  height: 100px;
}
<p>Drag files and/or directories to the box below!</p>

<div id="dropzone">
  <div id="boxtitle">
    Drop Files Here
  </div>
</div>

<h2>Directory tree:</h2>

<ul id="listing"></ul>

webkitGetAsEntry поддерживается Chrome 13+, Firefox 50+ и Edge.

источник: https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry