Dosya gezgininden açılan dosyaları işleme

Palances Liao
Palances Liao

Modern yöntem

File Handling API'yi kullanma

Öncelikle, web uygulaması manifestinizde file_handlers özelliğini bildirin. Dosya İşleme API'si, action özelliğini (bir işleme URL'si) ve accept özelliğini belirtmenizi gerektirir. Bu özellik, anahtar olarak MIME türlerini ve özellikle karşılık gelen dosya uzantılarının dizilerini içeren bir nesnedir.

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

Ardından, açılan dosyaları launchQueue aracılığıyla zorunlu olarak işlemek için File Handling API'yi kullanmanız gerekir.

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.
    }
  });
}

Browser Support

  • Chrome: 102.
  • Edge: 102.
  • Firefox: not supported.
  • Safari: not supported.

Source

Klasik yöntem

Klasik DataTransferItem.getAsFile() yöntemini kullanma

Dosya İşleme API'si desteklenmiyorsa dosyaları dosya gezgininden uygulamaya sürükleyip bırakmaya devam edebilirsiniz. DataTransferItem.getAsFile() yöntemi, sürükleme verisi öğesinin File nesnesini döndürür. Öğe bir dosya değilse bu yöntem null değerini döndürür. Dosyayı okuyabilirsiniz ancak dosyaya geri yazamazsınız. Bu yöntemin dizinleri desteklememesi dezavantajıdır.

Browser Support

  • Chrome: 11.
  • Edge: 12.
  • Firefox: 50.
  • Safari: 5.1.

Source

Progresif geliştirme

Aşağıdaki snippet, File Handling API'yi kullanılabilir olduğunda kullanır ve ayrıca sürüklenen dosyaların işlenebilmesi için sürükle ve bırak işleyicilerini kaydeder.

Web uygulaması manifestinde işlenebilecek dosya türlerini bildirin. Dosya İşleme API'sini desteklemeyen tarayıcılar bunu yoksayar.

{
  "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.
    }
  }
});

Daha fazla bilgi

Demo

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}

`; } }); }