DataTransferItem:webkitGetAsEntry() 方法
如果 DataTransferItem 所描述的項是檔案,則 webkitGetAsEntry() 返回一個表示該檔案的 FileSystemFileEntry 或 FileSystemDirectoryEntry。如果該項不是檔案,則返回 null。
注意:目前,非 WebKit 瀏覽器(包括 Firefox)將此函式實現為 webkitGetAsEntry();將來它可能會被重新命名為 getAsEntry(),因此您應該編寫防禦性程式碼,同時查詢兩者。
語法
webkitGetAsEntry()
引數
無。
返回值
一個基於 FileSystemEntry 的物件,用於描述拖放的項。這將是 FileSystemFileEntry 或 FileSystemDirectoryEntry。如果拖放的項不是檔案,或者 DataTransferItem 物件不是讀取或讀/寫模式,則方法會中止並返回 null。
示例
在此示例中,建立了一個放置區,它透過掃描拖放的檔案和目錄來響應 drop 事件,並輸出分層的目錄列表。
HTML
HTML 建立了放置區本身,它是一個 ID 為 "dropzone" 的 <div> 元素,以及一個 ID 為 "listing" 的無序列表元素。
<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
示例使用的樣式顯示在此處。
#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 個條目。
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 事件被預設處理程式處理,以便我們的放置區可以接收拖放操作
dropzone.addEventListener("dragover", (event) => {
event.preventDefault();
});
當然,啟動一切的事件處理程式是 drop 事件的處理程式。
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 |
瀏覽器相容性
載入中…