DataTransferItem: webkitGetAsEntry() 方法

如果由DataTransferItem描述的项目是文件,则webkitGetAsEntry()返回一个FileSystemFileEntryFileSystemDirectoryEntry,表示该文件。如果该项目不是文件,则返回null

注意:此函数在非 WebKit 浏览器(包括 Firefox)中实现为webkitGetAsEntry();将来可能会将其重命名为getAsEntry(),因此您应该进行防御性编码,查找两者。

语法

js
webkitGetAsEntry()

参数

无。

返回值

一个FileSystemEntry基于的对象,描述了被拖放的项目。这将是FileSystemFileEntryFileSystemDirectoryEntry。如果被拖放的项目不是文件,或者DataTransferItem对象不是处于读取或读/写模式,则该方法将中止并返回null

示例

在此示例中,创建了一个放置区域,该区域响应drop事件,方法是扫描拖放的文件和目录,并输出分层目录列表。

HTML

HTML 本身建立了放置区域,它是一个具有 ID "dropzone"<div>元素,以及一个具有 ID "listing"的无序列表元素。

html
<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>

CSS

此处显示了示例使用的样式。

css
#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;
}

body {
  font:
    14px "Arial",
    sans-serif;
}

JavaScript

首先,让我们看看递归函数scanFiles()。此函数将表示要扫描和处理的文件系统中的条目的FileSystemEntryitem参数)和要将内容列表插入其中的元素(container参数)作为输入。

注意:要读取目录中的所有文件,需要重复调用readEntries,直到它返回一个空数组。在基于 Chromium 的浏览器中,以下示例仅返回最多 100 个条目。

js
let dropzone = document.getElementById("dropzone");
let listing = document.getElementById("listing");

function scanFiles(item, container) {
  let elem = document.createElement("li");
  elem.textContent = item.name;
  container.appendChild(elem);

  if (item.isDirectory) {
    let directoryReader = item.createReader();
    let directoryContainer = document.createElement("ul");
    container.appendChild(directoryContainer);
    directoryReader.readEntries((entries) => {
      entries.forEach((entry) => {
        scanFiles(entry, directoryContainer);
      });
    });
  }
}

scanFiles()首先创建一个新的<li>元素来表示正在扫描的项目,将其文本内容插入项目名称,然后将其追加到容器中。在此示例中,容器始终是列表元素,您很快就会看到。

将当前项目添加到列表后,将检查项目的isDirectory属性。如果该项目是目录,我们需要递归进入该目录。第一步是创建一个FileSystemDirectoryReader来处理获取目录的内容。这是通过调用项目的createReader()方法完成的。然后创建一个新的<ul>并将其追加到父列表;这将在列表层次结构的下一级包含目录的内容。

之后,调用directoryReader.readEntries()以读取目录中的所有条目。然后,这些条目依次传递到对scanFiles()的递归调用中以进行处理。任何是文件的文件都将插入到列表中;任何是目录的文件都将插入到列表中,并且在下面添加了列表层次结构的新级别,依此类推。

然后是事件处理程序。首先,我们阻止dragover事件由默认处理程序处理,以便我们的放置区域可以接收放置

js
dropzone.addEventListener(
  "dragover",
  (event) => {
    event.preventDefault();
  },
  false,
);

当然,启动所有操作的事件处理程序是drop事件的处理程序

js
dropzone.addEventListener(
  "drop",
  (event) => {
    let items = event.dataTransfer.items;

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

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

      if (item) {
        scanFiles(item, listing);
      }
    }
  },
  false,
);

这将获取表示从event.dataTransfer.items拖放的项目的DataTransferItem对象列表。然后我们调用Event.preventDefault()以防止在完成操作后进一步处理该事件。

现在是时候开始构建列表了。首先,通过将listing.textContent设置为为空来清空列表。这让我们可以得到一个空的<ul>,开始将目录条目插入其中。

然后我们遍历拖放项目列表中的项目。对于每个项目,我们调用其webkitGetAsEntry()方法以获取表示该文件的FileSystemEntry。如果成功,我们调用scanFiles()来处理该项目——如果它只是一个文件,则将其添加到列表中;如果它是一个目录,则将其添加并向下遍历。

结果

您可以通过在下面尝试来查看它是如何工作的。找到一些文件和目录并将其拖入,然后查看结果输出。

规范

规范
文件和目录条目 API
# dom-datatransferitem-webkitgetasentry

浏览器兼容性

BCD 表格仅在启用了 JavaScript 的浏览器中加载。

另请参阅