איך לטפל בקבצים שנפתחו מסייר הקבצים

פלאנס ליאו
פלאנס ליאו

הדרך המודרנית

שימוש ב-File Treatment API

קודם כול, צריך להצהיר על המאפיין file_handlers בקובץ המניפסט של אפליקציית האינטרנט. כדי להשתמש ב-File Treatment API, צריך לציין את המאפיין action (כתובת URL לטיפול) ואת המאפיין accept, שהוא אובייקט עם סוגי MIME כמפתחות ומערכים של סיומות הקבצים התואמות במיוחד.

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

בשלב הבא, צריך להשתמש ב-File Treatment 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 Treatment API לא נתמך, תוכלו בכל זאת לגרור ולשחרר קבצים מסייר הקבצים אל האפליקציה. השיטה DataTransferItem.getAsFile() מחזירה את האובייקט File של פריט הגרירה. אם הפריט אינו קובץ, השיטה הזו מחזירה null. למרות שאתם יכולים לקרוא את הקובץ, לא ניתן לכתוב אליו חזרה. לשיטה הזו יש חיסרון שהיא לא תומכת בספריות.

תמיכה בדפדפן

  • 11
  • 12
  • 50
  • 5.1

מקור

שיפור הדרגתי

בקטע הקוד שבהמשך נעשה שימוש ב-File Treatment API, אם הוא זמין, וכן מתבצע רישום של רכיבי handler של גרירה ושחרור כדי שניתן יהיה לטפל בקבצים שגוררים.

יש להצהיר על סוגי הקבצים שניתן לטפל בהם במניפסט של אפליקציית האינטרנט. דפדפנים שלא תומכים ב-File Treatment 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}

`; } }); }