Antarmuka Tarik lalu Lepas HTML memungkinkan aplikasi web menerima file yang ditarik lalu dilepas di halaman web. Selama operasi tarik lalu lepas, item file dan direktori yang ditarik dikaitkan dengan entri file dan entri direktori. Terkait penarikan lalu pelepasan file ke browser, ada dua cara untuk melakukannya: cara modern dan cara klasik.
Cara modern
Menggunakan metode DataTransferItem.getAsFileSystemHandle() File System Access API
Metode DataTransferItem.getAsFileSystemHandle() menampilkan promise dengan objek FileSystemFileHandle jika item yang ditarik adalah file, dan promise dengan objek FileSystemDirectoryHandle jika item yang ditarik adalah direktori. Dengan handle ini, Anda dapat membaca, dan secara opsional menulis kembali ke file atau direktori. Perhatikan bahwa DataTransferItem.kind antarmuka Tarik lalu Lepas akan
"file" untuk file dan direktori, sedangkan FileSystemHandle.kind File System Access API akan
"file" untuk file dan "directory" untuk direktori.
Cara klasik
Menggunakan metode DataTransferItem.getAsFile() klasik
Metode DataTransferItem.getAsFile() menampilkan objek File item data penarikan. Jika item bukan file, metode ini akan menampilkan null. Meskipun Anda dapat membaca file, tidak ada cara untuk menulis kembali
ke file tersebut. Metode ini memiliki kekurangan karena tidak mendukung direktori.
{i>Progressive enhancement <i}
Cuplikan di bawah menggunakan metode DataTransferItem.getAsFileSystemHandle() File System Access API modern saat didukung, lalu melakukan penggantian ke metode DataTransferItem.webkitGetAsEntry() non-standar, dan akhirnya melakukan penggantian ke metode DataTransferItem.getAsFile() klasik. Pastikan untuk memeriksa jenis setiap handle, karena bisa berupa salah satu dari:
FileSystemFileHandlesaat jalur kode modern dipilih.Filesaat jalur kode klasik dipilih.
Semua jenis memiliki properti name, jadi mencatatnya tidak masalah dan akan selalu berfungsi.
// Run feature detection.
const supportsFileSystemAccessAPI =
'getAsFileSystemHandle' in DataTransferItem.prototype;
// This is the drag and drop zone.
const elem = document.querySelector('main');
// Prevent navigation.
elem.addEventListener('dragover', (e) => {
e.preventDefault();
});
// Visually highlight the drop zone.
elem.addEventListener('dragenter', (e) => {
elem.style.outline = 'solid red 1px';
});
// Visually unhighlight the drop zone.
elem.addEventListener('dragleave', (e) => {
elem.style.outline = '';
});
// This is where the drop is handled.
elem.addEventListener('drop', async (e) => {
// Prevent navigation.
e.preventDefault();
// Unhighlight the drop zone.
elem.style.outline = '';
// Prepare an array of promises…
const fileHandlesPromises = [...e.dataTransfer.items]
// …by including only files (where file misleadingly means actual file _or_
// directory)…
.filter((item) => item.kind === 'file')
// …and, depending on previous feature detection…
.map((item) =>
supportsFileSystemAccessAPI
// …either get a modern `FileSystemHandle`…
? item.getAsFileSystemHandle()
// …or a classic `File`.
: item.getAsFile(),
);
// Loop over the array of promises.
for await (const handle of fileHandlesPromises) {
// This is where we can actually exclusively act on the files.
if (handle.kind === 'file' || handle.isFile) {
console.log(`File: ${handle.name}`);
}
}
});
Bacaan lebih lanjut
Demo
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>How to drag and drop files</title>
</head>
<body>
<main>
<h1>How to drag and drop files</h1>
<p>Drag and drop one or multiple files onto the page.</p>
<pre></pre>
</main>
</body>
</html>CSS
:root {
color-scheme: dark light;
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 1rem;
font-family: system-ui, sans-serif;
line-height: 1.5;
min-height: 100vh;
display: flex;
flex-direction: column;
}
img,
video {
height: auto;
max-width: 100%;
}
main {
flex-grow: 1;
}
footer {
margin-top: 1rem;
border-top: solid CanvasText 1px;
font-size: 0.8rem;
}
JS
const supportsFileSystemAccessAPI =
"getAsFileSystemHandle" in DataTransferItem.prototype;
const supportsWebkitGetAsEntry =
"webkitGetAsEntry" in DataTransferItem.prototype;
const elem = document.querySelector("main");
const debug = document.querySelector("pre");
elem.addEventListener("dragover", (e) => {
// Prevent navigation.
e.preventDefault();
});
elem.addEventListener("dragenter", (e) => {
elem.style.outline = "solid red 1px";
});
elem.addEventListener("dragleave", (e) => {
elem.style.outline = "";
});
elem.addEventListener("drop", async (e) => {
e.preventDefault();
elem.style.outline = "";
const fileHandlesPromises = [...e.dataTransfer.items]
.filter((item) => item.kind === "file")
.map((item) =>
supportsFileSystemAccessAPI
? item.getAsFileSystemHandle()
: supportsWebkitGetAsEntry
? item.webkitGetAsEntry()
: item.getAsFile()
);
for await (const handle of fileHandlesPromises) {
if (handle.kind === "directory" || handle.isDirectory) {
console.log(`Directory: ${handle.name}`);
debug.textContent += `Directory: ${handle.name}\n`;
} else {
console.log(`File: ${handle.name}`);
debug.textContent += `File: ${handle.name}\n`;
}
}
});