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 dosyadan oluşan bir 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 sağlar.

Tarayıcı desteği

Tarayıcı desteği

  • Chrome: 86.
  • Edge: 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

Ele almak istediğim ilk kullanım alanı, kullanıcıdan bir dosya seçmesini istemek, ardından bu dosyayı diskten açıp okumaktır.

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

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 adı dizisi döndürür. İsteğe bağlı options parametresi, dosya seçicinin davranışını etkilemenize olanak tanır. Örneğin, kullanıcının birden fazla dosya, dizin veya farklı dosya türü seçmesine izin vererek bu parametreyi kullanabilirsiniz. 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 mükemmel bir seçenektir.

Diğer birçok güçlü API gibi showOpenFilePicker() çağrısı da güvenli bir bağlamda yapılmalı ve kullanıcı hareketi 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çtikten sonra showOpenFilePicker(), bir tutamaç dizisi döndürür. Bu durumda, dosyayla etkileşim kurmak için gereken özellikleri ve yöntemleri içeren bir FileSystemFileHandle içeren tek bir öğe dizisi döndürülür.

Daha sonra kullanılabilmesi için dosya tutamacına referans tutmak yararlı olur. Dosyadaki değişiklikleri kaydetmek veya başka dosya işlemleri yapmak için oturum açmanız gerekir.

Dosya sisteminden dosya okuma

Dosyanın bir tutamacına sahip olduğunuza 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 okumak için yeni bir File nesnesi almak üzere getFile() işlevini 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 Olarak Kaydet yeni bir dosya oluşturduğundan yeni bir dosya tutamaç gerektirir.

Yeni dosya oluşturma

Dosya kaydetmek için showSaveFilePicker() öğesini çağırın. Bu işlem, dosya seçiciyi "kaydet" modunda gösterir ve kullanıcının kaydetmek için kullanmak istediği yeni bir dosya 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 kaydetme

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 süreç 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 işlenir.

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() ya da 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'],
    },
  }],
});

Varsayılan başlangıç dizini için de aynı durum 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 bir startIn mülkü 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 depolandığı 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çicilerinin amacını belirtme

Bazen uygulamalarda farklı amaçlar için farklı seçicilere yer verilir. Örneğin, zengin metin düzenleyiciler kullanıcıların metin dosyalarını açmasına ve resimleri içe aktarmasına 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 saklayarak bu sorunun üstesinden gelebilirsiniz. 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);
  }
});

Kayıtlı dosya veya dizin herkese açık adları 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 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 bu dosyalara ve klasörlere erişme

Bir dizinden getFileHandle() veya sırasıyla 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 dosya veya klasörlerle çalışırken söz konusu öğenin yolunu çözmek 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"]

Bir dizindeki dosya ve klasörleri silme

Bir dizine erişim elde ettiyseniz removeEntry() yöntemini kullanarak içindeki dosya ve klasörleri silebilirsiniz. Klasörler için silme işlemi isteğe bağlı olarak yinelemeli olabilir ve tüm alt klasörleri ve bu klasörlerdeki dosyaları içerebilir.

// 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();

Dosyaları 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 adı içeren bir dize veya hedef klasöre giden 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 girişte bu durum 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 özel dosya sistemine erişme

Kaynak özel dosya sistemi, adından da anlaşılacağı gibi sayfanın kaynağına özel 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

Performans için optimize edilmiş dosyalara kaynak gizli dosya sisteminden 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, dosya sistemi erişim API'sini 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 tanımlanan temel ilkeleri temel almıştır.

Dosya açma veya yeni dosya kaydetme

Dosya seçici, okumak için bir dosya açma
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"> öğesiyle aynı davranıştır.

Dosyayı diske kaydetmek için dosya seçici.
Dosyaları diske kaydetmek için kullanılan bir 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ı cihaza yeni bir dosya kaydettiğinde (mevcut bir dosyanın üzerine yazmadığında) 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ık klasörleri) kaydetme özelliğini sınırlayabilir. Bu durumda tarayıcı bir istem gösterir ve kullanıcıdan farklı bir klasör seçmesini ister.

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.
Tarayıcıya mevcut bir dosya üzerinde yazma izni verilmeden önce kullanıcılara gösterilen istem.

Alternatif olarak, IDE gibi birden fazla dosyayı düzenleyen bir web uygulaması, açılma sırasında değişiklikleri kaydetme izni de 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ı tarafından web sitesine yerel bir dosyaya kaydetme izni verildiğini belirten 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ı dilediğinde bu erişimi 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 ihtiyaç duyduğunuz yöntemler veya özellikler eksik mi? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var?

Uygulamayla ilgili sorun mu yaşıyorsunuz?

Chrome'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, özelliklere öncelik vermemize yardımcı olur ve diğer tarayıcı tedarikçi firmalarına bu özellikleri 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.