File System Access API: yerel dosyalara erişimi kolaylaştırma

File System Access API, web uygulamalarının değişiklikleri doğrudan kullanıcının cihazındaki dosya ve klasörlere okumasına veya kaydetmesine olanak tanır.

File System Access API nedir?

Dosya Sistemi Erişimi API'si, geliştiricilerin kullanıcının yerel cihazındaki dosyalarla etkileşime geçen güçlü web uygulamaları (ör. IDE'ler, fotoğraf ve video düzenleyiciler, metin düzenleyiciler vb.) oluşturmasını sağlar. Bir kullanıcı bir web uygulamasına erişim izni verdikten sonra bu API, kullanıcının değişiklikleri doğrudan cihazındaki dosyalara ve klasörlere okumasına veya kaydetmesine olanak tanır. File System Access API, dosya okuma ve yazmanın yanı sıra bir dizini açma ve içeriğini listeleme olanağı da sunar.

Daha önce dosya okuma ve yazmayla çalıştıysanız paylaşacağım bilgilerin çoğu size tanıdık gelecektir. Tüm sistemler birbirinin aynısı olmadığından bu dokümanı okumanızı öneririz.

Dosya Sistemi Erişimi API'si, Windows, macOS, ChromeOS ve Linux'taki çoğu Chromium tarayıcıda desteklenir. Bununla birlikte, Brave'da bu özellik şu anda yalnızca bir bayrak aracılığıyla kullanılabilir. Android desteği için crbug.com/1011535 kapsamında çalışmalar devam etmektedir.

File System Access API'yi kullanma

File System Access API'nin gücünü ve kullanışlılığını göstermek için tek bir dosyalı metin düzenleyici yazdım. Bir metin dosyasını açmanıza, düzenlemenize, değişiklikleri diske kaydetmenize veya yeni bir dosya başlatıp değişiklikleri diske kaydetmenize olanak tanır. Çok ayrıntılı olmasa da kavramları anlamanıza yardımcı olacak kadar bilgi içerir.

Tarayıcı desteği

Tarayıcı desteği

  • Chrome: 86.
  • Kenar: 86.
  • Firefox: Desteklenmez.
  • Safari: desteklenmez.

Kaynak

Özellik algılama

File System Access API'nin desteklenip desteklenmediğini öğrenmek için ilgilendiğiniz seçici yöntemin olup olmadığını kontrol edin.

if ('showOpenFilePicker' in self) {
  // The `showOpenFilePicker()` method of the File System Access API is supported.
}

Dene

File System Access API'nin metin düzenleyici demosunda nasıl kullanıldığını görün.

Yerel dosya sisteminden dosya okuma

Yapmak istediğim ilk kullanım alanı, kullanıcıdan dosya seçmesini, ardından bu dosyayı diskten açıp okumasını istemek.

Kullanıcıdan okunacak bir dosya seçmesini isteyin

File System Access API'nin giriş noktası window.showOpenFilePicker(). Çağrıldığında bir dosya seçici iletişim kutusu gösterir ve kullanıcıdan bir dosya seçmesini ister. Kullanıcı bir dosya seçtikten sonra API, bir dosya tutamaç dizisi döndürür. İsteğe bağlı options parametresi, örneğin kullanıcının birden fazla dosya, dizin ya da farklı dosya türleri seçmesine izin vererek dosya seçicinin davranışını etkilemenize olanak tanır. Dosya seçici, herhangi bir seçenek belirtilmeden kullanıcının tek bir dosya seçmesine olanak tanır. Bu, metin düzenleyiciler için idealdir.

Diğer birçok güçlü API gibi showOpenFilePicker() çağrısı da güvenli bağlamda yapılmalı ve kullanıcı hareketinin içinden çağrılmalıdır.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
  // Destructure the one-element array.
  [fileHandle] = await window.showOpenFilePicker();
  // Do something with the file handle.
});

Kullanıcı bir dosya seçtiğinde showOpenFilePicker(), herkese açık kullanıcı adları dizisi döndürür. Bu örnekte, dosyayla etkileşime geçmek için gerekli özellikleri ve yöntemleri içeren FileSystemFileHandle değerine sahip tek öğeli bir dizi gösterilir.

Daha sonra kullanılabilmesi için dosya herkese açık kullanıcı adını referans tutmanızda fayda vardır. Dosyadaki değişiklikleri kaydetmek veya başka dosya işlemleri yapmak için oturum açmanız gerekir.

Dosya sisteminden dosya okuma

Artık bir dosyanın herkese açık kullanıcı adını bildiğinize göre dosyanın özelliklerini alabilir veya dosyanın kendisine erişebilirsiniz. Şimdilik içeriğini okuyacağım. handle.getFile() çağrısı, bir blob içeren bir File nesnesi döndürür. Blob'daki verileri almak için yöntemlerinden birini (slice(), stream(), text() veya arrayBuffer()) çağırın.

const file = await fileHandle.getFile();
const contents = await file.text();

FileSystemFileHandle.getFile() tarafından döndürülen File nesnesi yalnızca diskteki temel dosya değişmediği sürece okunabilir. Diskteki dosya değiştirilirse File nesnesi okunamaz hale gelir ve değiştirilen verileri okuyacak yeni bir File nesnesi almak için getFile() öğesini tekrar çağırmanız gerekir.

Tüm unsurların birleşimi

Kullanıcılar düğmesini tıkladığında tarayıcıda bir dosya seçici gösterilir. Kullanıcı bir dosya seçtikten sonra uygulama, içeriği okur ve <textarea> içine yerleştirir.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
  [fileHandle] = await window.showOpenFilePicker();
  const file = await fileHandle.getFile();
  const contents = await file.text();
  textArea.value = contents;
});

Dosyayı yerel dosya sistemine yazma

Metin düzenleyicide dosyaları kaydetmenin iki yolu vardır: Kaydet ve Farklı Kaydet. Kaydet, daha önce alınan dosya adını kullanarak değişiklikleri orijinal dosyaya geri yazar. Ancak Farklı Kaydet, yeni bir dosya oluşturur ve bu nedenle yeni bir dosya herkese açık kullanıcı adı gerektirir.

Yeni dosya oluşturma

Bir dosyayı kaydetmek için showSaveFilePicker() çağrısı yapın. Bu işlev, dosya seçiciyi "kaydetme" modunda göstererek kullanıcının kaydetmek için kullanmak istediği yeni bir dosyayı seçmesine olanak tanır. Metin düzenleyicinin otomatik olarak bir .txt uzantısı eklemesini de istediğim için bazı ek parametreler sağladım.

async function getNewFileHandle() {
  const options = {
    types: [
      {
        description: 'Text Files',
        accept: {
          'text/plain': ['.txt'],
        },
      },
    ],
  };
  const handle = await window.showSaveFilePicker(options);
  return handle;
}

Değişiklikleri diske kaydet

Değişiklikleri bir dosyaya kaydetmeyle ilgili tüm kodları GitHub'daki metin düzenleyici demomda bulabilirsiniz. Temel dosya sistemi etkileşimleri fs-helpers.js içindedir. En basit haliyle bu işlem aşağıdaki koda benzer. Her adımı adım adım açıklayacağım.

// fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
  // Create a FileSystemWritableFileStream to write to.
  const writable = await fileHandle.createWritable();
  // Write the contents of the file to the stream.
  await writable.write(contents);
  // Close the file and write the contents to disk.
  await writable.close();
}

Diske veri yazma işleminde, WritableStream alt sınıfı olan bir FileSystemWritableFileStream nesnesi kullanılır. Dosya tutamaç nesnesinde createWritable() çağrısı yaparak akışı oluşturun. createWritable() çağrıldığında tarayıcı önce kullanıcının dosyaya yazma izni verip vermediğini kontrol eder. Yazma izni verilmediyse tarayıcı kullanıcıdan izin ister. İzin verilmezse createWritable() bir DOMException atar ve uygulama dosyaya yazamaz. Metin düzenleyicide DOMException nesneleri saveFile() yönteminde ele alınır.

write() yöntemi, metin düzenleyici için gereken bir dize alır. Ancak BufferSource veya Blob da alabilir. Örneğin, bir akışı doğrudan bu akışa aktarabilirsiniz:

async function writeURLToFile(fileHandle, url) {
  // Create a FileSystemWritableFileStream to write to.
  const writable = await fileHandle.createWritable();
  // Make an HTTP request for the contents.
  const response = await fetch(url);
  // Stream the response into the file.
  await response.body.pipeTo(writable);
  // pipeTo() closes the destination pipe by default, no need to close it.
}

Ayrıca, dosyayı belirli bir konumda güncellemek veya yeniden boyutlandırmak için akışta seek() veya truncate() düğmesini de kullanabilirsiniz.

Önerilen bir dosya adı ve başlangıç dizini belirtme

Çoğu durumda uygulamanızın varsayılan bir dosya adı veya konum önermesini isteyebilirsiniz. Örneğin, bir metin düzenleyici Untitled yerine Untitled Text.txt dosya adını önerebilir. Bunu, showSaveFilePicker seçenekleri kapsamında bir suggestedName mülkü ile yapabilirsiniz.

const fileHandle = await self.showSaveFilePicker({
  suggestedName: 'Untitled Text.txt',
  types: [{
    description: 'Text documents',
    accept: {
      'text/plain': ['.txt'],
    },
  }],
});

Aynı durum varsayılan başlangıç dizini için de geçerlidir. Metin düzenleyici oluşturuyorsanız dosya kaydetme veya dosya açma iletişim kutusunu varsayılan documents klasöründe başlatmak isteyebilirsiniz. Resim düzenleyici oluşturuyorsanız varsayılan pictures klasöründe başlatmak isteyebilirsiniz. showSaveFilePicker, showDirectoryPicker() veya showOpenFilePicker yöntemlerine startIn özelliği ileterek varsayılan bir başlangıç dizini önerebilirsiniz.

const fileHandle = await self.showOpenFilePicker({
  startIn: 'pictures'
});

Bilinen sistem dizinlerinin listesi:

  • desktop: Kullanıcının masaüstü dizini (varsa).
  • documents: Kullanıcı tarafından oluşturulan dokümanların genellikle depolandığı dizin.
  • downloads: İndirilen dosyaların genellikle depolandığı dizin.
  • music: Ses dosyalarının genellikle depolandığı dizin.
  • pictures: Fotoğrafların ve diğer hareketsiz resimlerin genellikle depolanacağı dizin.
  • videos: Videoların veya filmlerin genellikle depolandığı dizin.

Bilinen sistem dizinlerinin yanı sıra, mevcut bir dosya veya dizin adını startIn için bir değer olarak da iletebilirsiniz. İletişim kutusu aynı dizinde açılır.

// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
  startIn: directoryHandle
});

Farklı dosya seçicilerin amacını belirtme

Bazen uygulamalarda farklı amaçlar için farklı seçiciler bulunur. Örneğin, zengin metin düzenleyici, kullanıcının metin dosyalarını açmasına ve resimleri içe aktarmasına da olanak tanıyabilir. Varsayılan olarak her dosya seçici, en son hatırlanan konumda açılır. Her seçici türü için id değerleri depolayarak bu durumu atlatabilirsiniz. Bir id belirtilirse dosya seçici uygulaması, söz konusu id için ayrı bir son kullanılan dizini hatırlar.

const fileHandle1 = await self.showSaveFilePicker({
  id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
  id: 'importImage',
});

Dosya veya dizin tutamaçlarını IndexedDB'de depolama

Dosya ve dizin kalemleri serileştirilebilir. Bu, bir dosya veya dizin kalemini IndexedDB'e kaydedebileceğiniz ya da aynı üst düzey kaynak arasında göndermek için postMessage() işlevini çağırabileceğiniz anlamına gelir.

Dosya veya dizin tutamaçlarını IndexedDB'e kaydetmek, durumu depolayabileceğiniz veya kullanıcının üzerinde çalıştığı dosya ya da dizinleri hatırlayabileceğiniz anlamına gelir. Bu sayede, son açılan veya düzenlenen dosyaların listesini tutabilir, uygulama açıldığında son dosyayı yeniden açma seçeneği sunabilir, önceki çalışma dizinlerini geri yükleyebilir ve daha pek çok işlem yapabilirsiniz. Metin düzenleyicide, kullanıcının açtığı en son beş dosyanın listesini depolarız. Böylece kullanıcı bu dosyalara tekrar erişebilir.

Aşağıdaki kod örneğinde, bir dosya tutamaç ve dizin tutamaç depolama ve alma işlemleri gösterilmektedir. Bu özelliğin işleyiş şeklini Glitch'te görebilirsiniz. (Kısaltmak için idb-keyval kitaplığını kullanıyorum.)

import { get, set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';

const pre1 = document.querySelector('pre.file');
const pre2 = document.querySelector('pre.directory');
const button1 = document.querySelector('button.file');
const button2 = document.querySelector('button.directory');

// File handle
button1.addEventListener('click', async () => {
  try {
    const fileHandleOrUndefined = await get('file');
    if (fileHandleOrUndefined) {
      pre1.textContent = `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    const [fileHandle] = await window.showOpenFilePicker();
    await set('file', fileHandle);
    pre1.textContent = `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});

// Directory handle
button2.addEventListener('click', async () => {
  try {
    const directoryHandleOrUndefined = await get('directory');
    if (directoryHandleOrUndefined) {
      pre2.textContent = `Retrieved directroy handle "${directoryHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    const directoryHandle = await window.showDirectoryPicker();
    await set('directory', directoryHandle);
    pre2.textContent = `Stored directory handle for "${directoryHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});

Depolanan dosya veya dizin işleyicileri ve izinleri

İzinler oturumlar arasında her zaman korunmadığından kullanıcının queryPermission() kullanarak dosyaya veya dizine izin verip vermediğini doğrulamanız gerekir. Bu bilgiler gönderilmediyse requestPermission() numaralı telefondan (yeniden) isteyebilirsiniz. Bu durum, dosya ve dizin imleçleri için de geçerlidir. Sırasıyla fileOrDirectoryHandle.requestPermission(descriptor) veya fileOrDirectoryHandle.queryPermission(descriptor) çalıştırmanız gerekir.

Metin düzenleyicide, kullanıcının daha önce izin verip vermediğini kontrol eden ve gerekirse isteği gönderen bir verifyPermission() yöntemi oluşturdum.

async function verifyPermission(fileHandle, readWrite) {
  const options = {};
  if (readWrite) {
    options.mode = 'readwrite';
  }
  // Check if permission was already granted. If so, return true.
  if ((await fileHandle.queryPermission(options)) === 'granted') {
    return true;
  }
  // Request permission. If the user grants permission, return true.
  if ((await fileHandle.requestPermission(options)) === 'granted') {
    return true;
  }
  // The user didn't grant permission, so return false.
  return false;
}

Okuma isteğiyle birlikte yazma izni isteyerek izin istemlerinin sayısını azalttım. Kullanıcı, dosyayı açarken bir istem görür ve hem okuma hem de yazma izni verir.

Bir dizini açma ve içeriğini numaralandırma

Bir dizindeki tüm dosyaları numaralandırmak için showDirectoryPicker() işlevini çağırın. Kullanıcı, seçicide bir dizin seçtikten sonra dizinin dosyalarını saymanıza ve bunlara erişmenize olanak tanıyan bir FileSystemDirectoryHandle döndürülür. Varsayılan olarak, dizindeki dosyalara okuma erişiminiz olur ancak yazma erişimine ihtiyacınız varsa yönteme { mode: 'readwrite' } değerini iletebilirsiniz.

butDir.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  for await (const entry of dirHandle.values()) {
    console.log(entry.kind, entry.name);
  }
});

Örneğin, her bir dosya boyutunu elde etmek için her dosyaya getFile() kullanarak erişmeniz gerekiyorsa her sonuçta await'ü sırayla kullanmayın. Bunun yerine, tüm dosyaları paralel olarak işleyin (örneğin, Promise.all() kullanarak).

butDir.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  const promises = [];
  for await (const entry of dirHandle.values()) {
    if (entry.kind !== 'file') {
      continue;
    }
    promises.push(entry.getFile().then((file) => `${file.name} (${file.size})`));
  }
  console.log(await Promise.all(promises));
});

Bir dizinde dosya ve klasör oluşturma veya bunlara erişme

Dizinde, getFileHandle() veya getDirectoryHandle() yöntemini kullanarak dosya ve klasör oluşturabilir ya da bunlara erişebilirsiniz. create anahtarına ve true veya false boole değerine sahip isteğe bağlı bir options nesnesi göndererek, mevcut değilse yeni bir dosya veya klasör oluşturulup oluşturulmayacağını belirleyebilirsiniz.

// In an existing directory, create a new directory named "My Documents".
const newDirectoryHandle = await existingDirectoryHandle.getDirectoryHandle('My Documents', {
  create: true,
});
// In this new directory, create a file named "My Notes.txt".
const newFileHandle = await newDirectoryHandle.getFileHandle('My Notes.txt', { create: true });

Bir dizindeki öğenin yolunu çözümleme

Bir dizindeki dosyalar veya klasörlerle çalışırken söz konusu öğenin yolunun çözülmesi yararlı olabilir. Bu işlem, uygun şekilde adlandırılmış resolve() yöntemiyle yapılabilir. Çözüm için öğe, dizinin doğrudan veya dolaylı bir alt öğesi olabilir.

// Resolve the path of the previously created file called "My Notes.txt".
const path = await newDirectoryHandle.resolve(newFileHandle);
// `path` is now ["My Documents", "My Notes.txt"]

Dizindeki dosya ve klasörleri silme

Bir dizine erişim elde ettiyseniz içerdiği dosya ve klasörleri removeEntry() yöntemini kullanarak silebilirsiniz. Klasörler için silme işlemi isteğe bağlı olarak yinelenebilir ve tüm alt klasörleri ve bunların içerdiği dosyaları içerir.

// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });

Dosya veya klasörleri doğrudan silme

Bir dosya veya dizin tutamacına erişiminiz varsa FileSystemFileHandle veya FileSystemDirectoryHandle üzerinde remove()'ü çağırarak tutamacıyı kaldırabilirsiniz.

// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();

Dosya ve klasörleri yeniden adlandırma ve taşıma

Dosya ve klasörler, FileSystemHandle arayüzünde move() çağrılarak yeniden adlandırılabilir veya yeni bir konuma taşınabilir. FileSystemHandle, FileSystemFileHandle ve FileSystemDirectoryHandle alt arayüzlerine sahiptir. move() yöntemi bir veya iki parametre alır. İlki, yeni ada sahip bir dize veya hedef klasör için bir FileSystemDirectoryHandle olabilir. İkinci durumda, isteğe bağlı ikinci parametre yeni adı içeren bir dizedir. Bu nedenle, taşıma ve yeniden adlandırma işlemi tek adımda yapılabilir.

// Rename the file.
await file.move('new_name');
// Move the file to a new directory.
await file.move(directory);
// Move the file to a new directory and rename it.
await file.move(directory, 'newer_name');

Sürükle ve bırak entegrasyonu

HTML sürükle ve bırak arayüzleri, web uygulamalarının bir web sayfasında sürüklenen ve bırakılan dosyaları kabul etmesini sağlar. Sürükle ve bırak işlemi sırasında sürüklenen dosya ve dizin öğeleri sırasıyla dosya girişleriyle ve dizin girişleriyle ilişkilendirilir. DataTransferItem.getAsFileSystemHandle() yöntemi, sürüklenen öğe bir dosyaysa FileSystemFileHandle nesnesi içeren bir promise, sürüklenen öğe bir dizinse FileSystemDirectoryHandle nesnesi içeren bir promise döndürür. Aşağıdaki listede bu uygulama çözümü gösterilmektedir. Sürükle ve bırak arayüzünün DataTransferItem.kind değerinin hem dosyalar hem de dizinler için "file" olduğunu, File System Access API'nin FileSystemHandle.kind değerinin ise dosyalar için "file", dizinler için "directory" olduğunu unutmayın.

elem.addEventListener('dragover', (e) => {
  // Prevent navigation.
  e.preventDefault();
});

elem.addEventListener('drop', async (e) => {
  e.preventDefault();

  const fileHandlesPromises = [...e.dataTransfer.items]
    .filter((item) => item.kind === 'file')
    .map((item) => item.getAsFileSystemHandle());

  for await (const handle of fileHandlesPromises) {
    if (handle.kind === 'directory') {
      console.log(`Directory: ${handle.name}`);
    } else {
      console.log(`File: ${handle.name}`);
    }
  }
});

Kaynak gizli dosya sistemine erişme

Kaynak özel dosya sistemi, adından da anlaşılacağı gibi sayfanın kaynağına özel olan bir depolama uç noktasıdır. Tarayıcılar bunu genellikle bu orijinal özel dosya sisteminin içeriğini bir diske kaydederek uygulasa da içeriğin kullanıcı tarafından erişilebilir olması amaçlanmaz. Benzer şekilde, kaynak özel dosya sisteminin alt öğelerinin adlarıyla eşleşen adlara sahip dosya veya dizinlerin bulunması beklenmez. Tarayıcı, orijinal özel dosya sistemi olduğu için dosya varmış gibi görünse de bu "dosyaları" bir veritabanında veya başka bir veri yapısında saklayabilir. Bu API'yi kullanırsanız oluşturulan dosyaların sabit diskte bire bir eşleştiğini beklemeyin. Kök FileSystemDirectoryHandle erişiminiz olduğunda, kaynak özel dosya sisteminde her zamanki gibi işlem yapabilirsiniz.

const root = await navigator.storage.getDirectory();
// Create a new file handle.
const fileHandle = await root.getFileHandle('Untitled.txt', { create: true });
// Create a new directory handle.
const dirHandle = await root.getDirectoryHandle('New Folder', { create: true });
// Recursively remove a directory.
await root.removeEntry('Old Stuff', { recursive: true });

Tarayıcı desteği

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 111.
  • Safari: 15.2.

Kaynak

Kaynak gizli dosya sisteminden performans için optimize edilmiş dosyalara erişme

Kaynak özel dosya sistemi, performans için yüksek düzeyde optimize edilmiş özel bir dosya türüne isteğe bağlı erişim sağlar. Örneğin, bir dosyanın içeriğine yerinde ve özel yazma erişimi sunar. Chromium 102 ve sonraki sürümlerde, kaynak özel dosya sisteminde dosya erişimini basitleştirmek için ek bir yöntem bulunur: createSyncAccessHandle() (eşzamanlı okuma ve yazma işlemleri için). FileSystemFileHandle üzerinde ancak yalnızca Web Çalışanlarında gösterilir.

// (Read and write operations are synchronous,
// but obtaining the handle is asynchronous.)
// Synchronous access exclusively in Worker contexts.
const accessHandle = await fileHandle.createSyncAccessHandle();
const writtenBytes = accessHandle.write(buffer);
const readBytes = accessHandle.read(buffer, { at: 1 });

Çoklu dolgu

File System Access API yöntemlerini tamamen polyfill olarak doldurmak mümkün değildir.

  • showOpenFilePicker() yöntemi, <input type="file"> öğesiyle yaklaşık olarak bulunabilir.
  • showSaveFilePicker() yöntemi, <a download="file_name"> öğesiyle simüle edilebilir. Ancak bu, programatik bir indirme tetikler ve mevcut dosyaların üzerine yazılmasına izin vermez.
  • showDirectoryPicker() yöntemi, standart olmayan <input type="file" webkitdirectory> öğesiyle bir dereceye kadar taklit edilebilir.

Mümkün olduğunda File System Access API'yi kullanan ve diğer tüm durumlarda en iyi ikinci seçeneklere başvuran browser-fs-access adlı bir kitaplık geliştirdik.

Güvenlik ve izinler

Chrome ekibi, File System Access API'yi tasarlarken ve uygularken kullanıcı denetimi, şeffaflık ve kullanıcı ergonomisi gibi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme başlıklı makalede belirtilen temel ilkeleri temel almıştır.

Dosya açma veya yeni dosya kaydetme

Okumak üzere bir dosyayı açmak için dosya seçici
Mevcut bir dosyayı okumak için açmak üzere kullanılan bir dosya seçici.

Kullanıcı, dosya seçiciyi kullanarak bir dosyayı veya dizini okuma izni verir. Açık dosya seçici, yalnızca güvenli bir bağlamda sunulurken kullanıcı hareketi kullanılarak gösterilebilir. Kullanıcılar fikrini değiştirirse dosya seçicideki seçimi iptal edebilir. Bu durumda site hiçbir şeye erişemez. Bu, <input type="file"> öğesinin davranışıyla aynıdır.

Dosyayı diske kaydetmek için dosya seçici.
Bir dosyayı diske kaydetmek için kullanılan dosya seçici.

Benzer şekilde, bir web uygulaması yeni bir dosya kaydetmek istediğinde tarayıcı, dosya kaydediciyi gösterir. Bu sayede kullanıcı yeni dosyanın adını ve konumunu belirtebilir. Kullanıcılar cihaza yeni bir dosya kaydettiğinden (mevcut bir dosyanın üzerine yazmaya karşı) dosya seçici, uygulamaya dosyaya yazma izni verir.

Kısıtlanmış klasörler

Tarayıcı, kullanıcıların ve verilerinin korunmasına yardımcı olmak için kullanıcının belirli klasörlere (ör. Windows gibi temel işletim sistemi klasörleri, macOS Kitaplığı klasörleri) dosya kaydetme olanağını sınırlayabilir. Bu durumda, tarayıcıda bir istem gösterilir ve kullanıcıdan farklı bir klasör seçmesi istenir.

Mevcut bir dosyayı veya dizini değiştirme

Web uygulamaları, kullanıcıdan açık izin almadan diskteki bir dosyayı değiştiremez.

İzin istemi

Bir kullanıcı daha önce okuma erişimi verdiği bir dosyaya yaptığı değişiklikleri kaydetmek isterse tarayıcı, sitenin değişiklikleri diske yazması için izin isteyen bir izin istemi gösterir. İzin isteği yalnızca kullanıcı hareketiyle (ör. Kaydet düğmesini tıklayarak) tetiklenebilir.

Dosya kaydetmeden önce gösterilen izin istemi.
Mevcut bir dosyada tarayıcıya yazma izni verilmeden önce kullanıcılara gösterilen istem.

Alternatif olarak, IDE gibi birden fazla dosyayı düzenleyen bir web uygulaması da açılış sırasında değişiklikleri kaydetmek için izin isteyebilir.

Kullanıcı İptal'i seçip yazma erişimi vermezse web uygulaması, değişiklikleri yerel dosyaya kaydedemez. Örneğin, "dosyayı indirme" veya verileri buluta kaydetme gibi bir yöntem sunarak kullanıcının verilerini kaydetmesi için alternatif bir yöntem sağlamalıdır.

Şeffaflık

Çok amaçlı adres çubuğu simgesi
Kullanıcının, web sitesine yerel dosyaya kaydetme izni verdiğini gösteren adres çubuğu simgesi.

Kullanıcı bir web uygulamasına yerel dosya kaydetme izni verdiğinde tarayıcı, adres çubuğunda bir simge gösterir. Simgeyi tıkladığınızda, kullanıcının erişim izni verdiği dosyaların listesini gösteren bir pop-up açılır. Kullanıcı dilerse bu erişimi her zaman iptal edebilir.

İzin kalıcılığı

Web uygulaması, kaynağına ait tüm sekmeler kapatılana kadar dosyaya yapılan değişiklikleri istemsiz olarak kaydetmeye devam edebilir. Bir sekme kapatıldığında site tüm erişimini kaybeder. Kullanıcı web uygulamasını bir sonraki sefer kullandığında, dosyalara erişim için tekrar istenir.

Geri bildirim

File System Access API ile ilgili deneyimlerinizi öğrenmek isteriz.

API tasarımı hakkında bilgi verin

API ile ilgili olarak beklediğiniz gibi çalışmayan bir şey var mı? Yoksa fikrinizi uygulamak için ihtiyacınız olan yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var?

Uygulamayla ilgili sorun mu yaşıyorsunuz?

Chrome&#39;un uygulamasında bir hata mı buldunuz? Yoksa uygulama, spesifikasyondan farklı mı?

  • https://new.crbug.com adresinden hata bildirin. Mümkün olduğunca fazla ayrıntı ve yeniden oluşturma talimatları eklediğinizden emin olun ve Bileşenler'i Blink>Storage>FileSystem olarak ayarlayın. Glitch, hızlı yeniden oluşturma işlemlerini paylaşmak için mükemmel bir araçtır.

API'yi kullanmayı planlıyor musunuz?

Sitenizde File System Access API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, özellikleri önceliklendirmemize yardımcı olur ve diğer tarayıcı tedarikçilerine bunları desteklemenin ne kadar önemli olduğunu gösterir.

Faydalı bağlantılar

Teşekkür ederiz

File System Access API spesifikasyonu Marijn Kruisselbrink tarafından yazılmıştır.