วิธีจัดการไฟล์ที่เปิดจากเครื่องมือสำรวจไฟล์

พาเลนซ์ เหลียว
Palances Liao

วิธีสมัยใหม่

การใช้ File Handling API

ก่อนอื่น ให้ประกาศแอตทริบิวต์ file_handlers ในไฟล์ Manifest ของเว็บแอป File Handling API กำหนดให้คุณต้องระบุพร็อพเพอร์ตี้ action (URL ที่ใช้จัดการ) และพร็อพเพอร์ตี้ accept ซึ่งเป็นออบเจ็กต์ที่มีประเภท MIME เป็นคีย์และอาร์เรย์ของนามสกุลไฟล์ที่เกี่ยวข้องโดยเฉพาะ

{
  "file_handlers": [
    {
      "action": "./",
      "accept": {
        "image/*": [".jpg", ".jpeg", ".png", ".webp", ".svg"]
      }
    }
  ]
}

ขั้นตอนต่อไป คุณต้องใช้ File Handling API เพื่อจัดการไฟล์ที่เปิดอยู่ผ่าน launchQueue

if ('launchQueue' in window && 'files' in LaunchParams.prototype) {
  launchQueue.setConsumer((launchParams) => {
    if (!launchParams.files.length) {
      return;
    }
    for (const fileHandle of launchParams.files) {
      // Handle the file.
    }
  });
}

การสนับสนุนเบราว์เซอร์

  • 102
  • 102
  • x
  • x

วิธีคลาสสิก

กำลังใช้เมธอด DataTransferItem.getAsFile() แบบคลาสสิก

หากระบบไม่รองรับ File Handling API คุณยังคงลากและวางไฟล์จากเครื่องมือสำรวจไฟล์ลงในแอปได้ โดยเมธอด DataTransferItem.getAsFile() จะแสดงผลออบเจ็กต์ File ของรายการข้อมูลลาก หากรายการไม่ใช่ไฟล์ เมธอดนี้จะแสดง null แม้ว่าจะอ่านไฟล์ได้ แต่จะเขียนกลับไปไม่ได้ วิธีนี้มีข้อเสียเนื่องจากไม่รองรับไดเรกทอรี

การสนับสนุนเบราว์เซอร์

  • 11
  • 12
  • 50
  • 5.1

แหล่งที่มา

การเพิ่มประสิทธิภาพแบบต่อเนื่อง

ข้อมูลโค้ดด้านล่างใช้ File Handling API เมื่อมีให้ใช้ และจะมีการลงทะเบียนตัวควบคุมแบบลากและวางเพิ่มเติมเพื่อให้จัดการไฟล์ที่ลากได้

ประกาศประเภทไฟล์ที่จัดการในไฟล์ Manifest ของเว็บแอปได้ เบราว์เซอร์ที่ไม่รองรับ File Handling API จะไม่สนใจเพียงเบราว์เซอร์นี้

{
  "file_handlers": [
    {
      "action": "./",
      "accept": {
        "image/*": [".jpg", ".jpeg", ".png", ".webp", ".svg"]
      }
    }
  ]
}
// File Handling API
const handleLaunchFiles = () => {
  window.launchQueue.setConsumer((launchParams) => {
    if (!launchParams.files.length) {
      return;
    }
    launchParams.files.forEach(async (handle) => {
      const file = await handle.getFile();
      console.log(`File: ${file.name}`);
      // Do something with the file.
    });
  });
};

if ('launchQueue' in window && 'files' in LaunchParams.prototype) {
  handleLaunchFiles();
}

// 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) => 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.isFile) {
      console.log(`File: ${handle.name}`);
      // Do something with the file.
    }
  }
});

อ่านเพิ่มเติม

เดโม

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="manifest" href="manifest.json" />
    <title>How to handle files opened from the file explorer</title>
    <link rel="stylesheet" href="style.css" />
    <!-- TODO: Devsite - Removed inline handlers -->
    <!-- <script>
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', async () => {
          const registration = await navigator.serviceWorker.register(
            'sw.js',
          );
          console.log(
            'Service worker registered for scope',
            registration.scope,
          );
        });
      }
    </script>
    <script src="script.js" type="module"></script> -->
  </head>
  <body>
    <h1>How to handle files opened from the file explorer</h1>
    <p>Install the app. After the installation, try opening an image file from the file explorer with the app.
  </body>
</html>

CSS


        html {
  box-sizing: border-box;
  font-family: system-ui, sans-serif;
  color-scheme: dark light;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
}

img {
  height: auto;
  max-width: 100%;
  display: block;
}
        

JS


        if ('launchQueue' in window && 'files' in LaunchParams.prototype) {
  launchQueue.setConsumer((launchParams) => {
    if (!launchParams.files.length) {
      return;
    }
    for (const fileHandle of launchParams.files) {
      document.body.innerHTML += `

${fileHandle.name}

`; } }); }