Dosya kaydetme

Thomas Steiner'ın yer aldığı daha fazla içerik
Thomas Steiner

Dosyalarla ilgilenme, web'deki uygulamaların en yaygın işlemlerinden biridir. Geleneksel olarak, kullanıcıların bir dosya yüklemesi, bu dosyada bazı değişiklikler yapması, ardından dosyayı tekrar indirmesi ve bunun sonucunda dosyanın İndirilenler klasörüne kopyalanması gerekiyordu. File System Access API ile kullanıcılar artık dosyaları doğrudan açabilir, değişiklikler yapabilir ve değişiklikleri orijinal dosyaya kaydedebilir.

Modern yöntem

File System Access API'nin showSaveFilePicker() yöntemini kullanma

Bir dosyayı kaydetmek için showSaveFilePicker() yöntemini çağırın. Bu durumda, FileSystemFileHandle ile ilgili bir söz döndürülür. İstediğiniz dosya adını yönteme { suggestedName: 'example.txt' } olarak aktarabilirsiniz.

Tarayıcı Desteği

  • 86
  • 86
  • x
  • x

Kaynak

Klasik yöntem

<a download> öğesini kullanma

Sayfadaki <a download> öğesi, kullanıcının bu öğeyi tıklayıp bir dosya indirmesine olanak tanır. Buradaki ipucu, öğeyi JavaScript içeren bir sayfaya görünmez bir şekilde eklemek ve programlı bir şekilde tıklamaktır.

Tarayıcı Desteği

  • 15
  • 13
  • 20
  • 10.1

Kaynak

Progresif geliştirme

Aşağıdaki yöntem, desteklendiğinde File System Access API'yi kullanır, aksi takdirde klasik yaklaşıma döner. İşlev her iki durumda da dosyayı kaydeder. Ancak File System Access API'nin desteklendiği yerlerde kullanıcıya bir dosya kaydetme iletişim kutusu gösterilir. Kullanıcılar burada dosyanın nereye kaydedileceğini seçebilir.

const saveFile = async (blob, suggestedName) => {
  // Feature detection. The API needs to be supported
  // and the app not run in an iframe.
  const supportsFileSystemAccess =
    'showSaveFilePicker' in window &&
    (() => {
      try {
        return window.self === window.top;
      } catch {
        return false;
      }
    })();
  // If the File System Access API is supported…
  if (supportsFileSystemAccess) {
    try {
      // Show the file save dialog.
      const handle = await showSaveFilePicker({
        suggestedName,
      });
      // Write the blob to the file.
      const writable = await handle.createWritable();
      await writable.write(blob);
      await writable.close();
      return;
    } catch (err) {
      // Fail silently if the user has simply canceled the dialog.
      if (err.name !== 'AbortError') {
        console.error(err.name, err.message);
        return;
      }
    }
  }
  // Fallback if the File System Access API is not supported…
  // Create the blob URL.
  const blobURL = URL.createObjectURL(blob);
  // Create the `<a download>` element and append it invisibly.
  const a = document.createElement('a');
  a.href = blobURL;
  a.download = suggestedName;
  a.style.display = 'none';
  document.body.append(a);
  // Programmatically click the element.
  a.click();
  // Revoke the blob URL and remove the element.
  setTimeout(() => {
    URL.revokeObjectURL(blobURL);
    a.remove();
  }, 1000);
};

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="icon"
      href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎉</text></svg>"
    />
    <title>How to save a file</title>
  </head>
  <body>
    <h1>How to save a file</h1>

    <label
      >Text to save
      <textarea rows="3">
Some sample text for you to save. Feel free to edit this.</textarea
      >
    </label>
    <label>File name <input class="text" value="example.txt" /></label>
    <button class="text" type="button">Save text</button>

    <label
      >Image to save
      <img
        src="https://cdn.glitch.global/75170424-3d76-41d7-ae77-72d0efb0401b/AVIF%20Test%20picture%20(JPEG%20converted%20to%20AVIF%20with%20Convertio).avif?v=1658240752363"
        alt="Blue flower."
        width="630"
        height="420"
    /></label>
    <label>File name <input class="img" value="example.avif" /></label>
    <button class="img" type="button">Save image</button>
  </body>
</html>

CSS


        :root {
  color-scheme: dark light;
}

html {
  box-sizing: border-box;
}

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

body {
  margin: 1rem;
  font-family: system-ui, sans-serif;
}

img {
  max-width: 320px;
  height: auto;
}

label,
button,
textarea,
input,
img {
  display: block;
  margin-block: 1rem;
}
        

JS


        const textarea = document.querySelector('textarea');
const textInput = document.querySelector('input.text');
const textButton = document.querySelector('button.text');

const img = document.querySelector('img');
const imgInput = document.querySelector('input.img');
const imgButton = document.querySelector('button.img');

const saveFile = async (blob, suggestedName) => {
  // Feature detection. The API needs to be supported
  // and the app not run in an iframe.
  const supportsFileSystemAccess =
    'showSaveFilePicker' in window &&
    (() => {
      try {
        return window.self === window.top;
      } catch {
        return false;
      }
    })();
  // If the File System Access API is supported…
  if (supportsFileSystemAccess) {
    try {
      // Show the file save dialog.
      const handle = await showSaveFilePicker({
        suggestedName,
      });
      // Write the blob to the file.
      const writable = await handle.createWritable();
      await writable.write(blob);
      await writable.close();
      return;
    } catch (err) {
      // Fail silently if the user has simply canceled the dialog.
      if (err.name !== 'AbortError') {
        console.error(err.name, err.message);
        return;
      }
    }
  }
  // Fallback if the File System Access API is not supported…
  // Create the blob URL.
  const blobURL = URL.createObjectURL(blob);
  // Create the `` element and append it invisibly.
  const a = document.createElement('a');
  a.href = blobURL;
  a.download = suggestedName;
  a.style.display = 'none';
  document.body.append(a);
  // Click the element.
  a.click();
  // Revoke the blob URL and remove the element.
  setTimeout(() => {
    URL.revokeObjectURL(blobURL);
    a.remove();
  }, 1000);
};

textButton.addEventListener('click', async () => {
  const blob = new Blob([textarea.value], { type: 'text/plain' });
  await saveFile(blob, textInput.value);
});

imgButton.addEventListener('click', async () => {
  const blob = await fetch(img.src).then((response) => response.blob());
  await saveFile(blob, imgInput.value);
});
        

Aksi belirtilmediği sürece bu sayfanın içeriği Creative Commons Atıf 4.0 Lisansı altında ve kod örnekleri Apache 2.0 Lisansı altında lisanslanmıştır. Ayrıntılı bilgi için Google Developers Site Politikaları'na göz atın. Java, Oracle ve/veya satış ortaklarının tescilli ticari markasıdır.

Son güncelleme tarihi: 2023-10-25 UTC.