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() 函式。此函式以 FileSystemEntry 作為輸入,該項表示要掃描和處理的檔案系統中的一個條目(item 引數),並以一個元素作為輸出,將內容列表插入其中(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();
});

當然,啟動一切的事件處理程式是 drop 事件的處理程式。

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

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

  for (const item of items) {
    const entry = item.webkitGetAsEntry();

    if (entry) {
      scanFiles(entry, listing);
    }
  }
});

這會從 event.dataTransfer.items 中獲取表示被拖放項的 DataTransferItem 物件列表。然後我們呼叫 Event.preventDefault() 來阻止在完成操作後事件被進一步處理。

現在是時候開始構建列表了。首先,透過將 listing.textContent 設定為空來清空列表。這樣我們就得到了一個空的 <ul> 來開始插入目錄條目。

然後我們遍歷被拖放項列表中的項。對於每一項,我們呼叫它的 webkitGetAsEntry() 方法來獲得一個表示該檔案的 FileSystemEntry。如果成功,我們就呼叫 scanFiles() 來處理該項——如果它只是一個檔案,就將其新增到列表中;如果它是一個目錄,就將其新增到列表中,並向下遍歷它。

結果

您可以透過嘗試下面的示例來了解它是如何工作的。找到一些檔案和目錄並將它們拖入,然後檢視生成的輸出。

規範

規範
File and Directory Entries API
# dom-datatransferitem-webkitgetasentry

瀏覽器相容性

另見