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

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

File System Access API nedir?

File System Access API (önceki adıyla Native File System API ve ondan önce Writeable Files API olarak adlandırılıyordu). Geliştiricilerin, kullanıcının yerel cihazındaki IDE'ler, fotoğraf ve video düzenleyiciler, metin düzenleyiciler gibi dosyalarla etkileşime giren güçlü web uygulamaları geliştirmesine olanak tanır. Kullanıcı bir web uygulamasına erişim izni verdikten sonra bu API, kullanıcının cihazındaki dosyalarda ve klasörlerde yapılan değişiklikleri doğrudan okumasına veya kaydetmesine olanak tanır. File System Access API dosya okuma ve yazmanın yanı sıra bir dizin açıp içeriğini numaralandırma özelliği de sunar.

Daha önce dosya okuma ve yazma konusunda çalıştıysanız, paylaşacaklarımın çoğu size tanıdık gelecektir. Tüm sistemler aynı olmadığından yine de okumanızı öneririm.

File System Access API şu anda Windows, macOS, ChromeOS ve Linux'taki çoğu Chromium tarayıcısında desteklenmektedir. Şu anda yalnızca bir bayrak arkasında kullanıma sunulduğu önemli bir istisna olan Brave'dir. Android, Chromium 109 tarihinden itibaren API'nin kaynak özel dosya sistemi kısmını desteklemektedir. Şu anda seçici yöntemleriyle ilgili herhangi bir plan yoktur, ancak crbug.com/1011535 adresine yıldız ekleyerek potansiyel ilerleme durumunu takip edebilirsiniz.

File System Access API'yi kullanma

File System Access API'nin gücünü ve faydasını göstermek için tek bir dosya metin düzenleyici yazdım. Bir metin dosyasını açmanıza, bu dosyayı düzenlemenize, değişiklikleri diske geri kaydetmenize veya yeni bir dosya başlatmanıza ve değişiklikleri diske kaydetmenize olanak tanır. Çok özel bir bilgi olmamasına rağmen kavramları anlamanıza yardımcı olacak kadar yararlı bilgiler sağlar.

Tarayıcı desteği

Tarayıcı Desteği

  • 86
  • 86
  • x
  • x

Kaynak

Deneyin

Metin düzenleyici demosunda File System Access API'yi çalışırken görün.

Yerel dosya sisteminden dosya okuma

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

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

File System Access API'nin giriş noktası window.showOpenFilePicker() şeklindedir. Çağrı yapıldığında bir dosya seçici iletişim kutusu gösterilir ve kullanıcıdan dosya seçmesi istenir. Kullanıcı bir dosya seçtikten sonra API, bir dizi dosya işleyicisi 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ürü seçmesine izin vererek dosya seçicinin davranışını etkilemenize olanak tanır. Herhangi bir seçenek belirtilmedikçe, dosya seçici kullanıcının tek bir dosya seçmesine olanak tanır. Bu, metin düzenleyiciler için mükemmeldir.

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

Daha sonra kullanılabilmesi için dosya tanıtıcısına bir referans tutmanız yararlı olur. Dosyadaki değişikliklerin kaydedilmesi veya diğer dosya işlemlerinin gerçekleştirilmesi gerekir.

Dosya sisteminden dosya okuma

Artık bir dosyaya yönelik tanıtıcınız olduğuna göre dosyanın özelliklerini alabilir veya dosyanın kendisine erişebilirsiniz. Şimdilik içeriğini okuyacağım. handle.getFile() çağrısı, blob içeren bir File nesnesi döndürür. Blobdan veri 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 dosyada değişiklik yapılırsa File nesnesi okunamaz hale gelir ve değiştirilen verileri okuyacak yeni bir File nesnesi almak için getFile() öğesini yeniden çağırmanız gerekir.

Özet

Kullanıcılar Aç 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 bir dosyayı kaydetmenin iki yolu vardır: Kaydet ve Farklı Kaydet. Kaydet seçeneği, daha önce alınan dosya tanıtıcısını kullanarak değişiklikleri orijinal dosyaya geri yazar. Ancak Farklı Kaydet yeni bir dosya oluşturur ve bu nedenle yeni bir dosya tanıtıcısı gerektirir.

Yeni dosya oluşturma

Bir dosyayı kaydetmek için showSaveFilePicker() yöntemini çağırın. Bu çağrı, dosya seçiciyi "kaydet" modunda gösterir ve kullanıcının kaydetmek için kullanmak istediği yeni bir dosyayı seçmesine olanak tanır. Ayrıca metin düzenleyici için .txt uzantısının otomatik olarak eklenmesini istedim. Bu yüzden 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

Bir dosyada yapılan değişiklikleri kaydetmek için gereken tüm kodları GitHub'daki metin düzenleyici demomuzda bulabilirsiniz. Temel dosya sistemi etkileşimleri fs-helpers.js içindedir. İşlem en basit şekilde aşağıdaki koda benzemektedir. Her bir adımı tek tek 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 yazılırken WritableStream alt sınıfı olan FileSystemWritableFileStream nesnesi kullanılır. Dosya işleyici nesnesinde createWritable() yöntemini çağırarak akışı oluşturun. createWritable() çağrıldığında, tarayıcı ilk olarak 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 gönderir ve uygulama dosyaya yazamaz. Metin düzenleyicide, DOMException nesneleri saveFile() yöntemiyle işlenir.

write() yöntemi, metin düzenleyici için gerekli olan bir dize alır. Ancak bir BufferSource veya Blob da alabilir. Örneğin, bir akışı doğrudan ona 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 konumdaki güncellemek ya da yeniden boyutlandırmak için akış içinde seek() veya truncate() aracını kullanabilirsiniz.

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

Çoğu durumda, uygulamanızın varsayılan bir dosya adı veya konumu önermesini isteyebilirsiniz. Örneğin, bir metin düzenleyici, Untitled yerine varsayılan dosya adını Untitled Text.txt önermek isteyebilir. Bunu, showSaveFilePicker seçeneklerinin parçası olarak bir suggestedName özelliği ileterek 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 söz konusudur. Bir metin düzenleyici oluşturuyorsanız dosya kaydetme veya dosya açma iletişim kutusunu varsayılan documents klasöründe, resim düzenleyicide ise varsayılan pictures klasöründe başlatmak isteyebilirsiniz. showSaveFilePicker, showDirectoryPicker() veya showOpenFilePicker yöntemlerine bir startIn özelliği ileterek varsayılan bir başlangıç dizini önerebilirsiniz.

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

İyi bilinen sistem dizinlerinin listesi şöyledir:

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

İyi bilinen sistem dizinlerinin dışında, mevcut bir dosya veya dizin tanıtıcısını da startIn değeri olarak iletebilirsiniz. Bunu yaptığınızda iletiş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 kullanılabilir. Örneğin, bir zengin metin düzenleyicisi, kullanıcının metin dosyalarını açmasına ve aynı zamanda 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ğerlerini depolayarak bu durumu atlatabilirsiniz. Bir id belirtilirse dosya seçici uygulaması, bu id için son kullanılan ayrı bir dizini hatırlar.

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

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

IndexedDB'deki dosya tanıtıcılarını veya dizin tanıtıcılarını depolama

Dosya tanıtıcıları ve dizin tanıtıcıları serileştirilebilir. Diğer bir deyişle, bir dosyayı veya dizin tanıtıcısını IndexedDB'ye kaydedebilir ya da bunları aynı üst düzey kaynak arasında göndermek için postMessage() yöntemini çağırabilirsiniz.

Dosya veya dizin tanıtıcılarını IndexedDB'ye kaydetmek, durumu depolayabileceğiniz veya bir kullanıcının hangi dosyalar ya da dizinler üzerinde çalıştığını hatırlayabileceğiniz anlamına gelir. Bu, son açılan veya düzenlenen dosyaların listesini saklamayı, uygulama açıldığında son dosyayı yeniden açmayı teklif etmeyi, önceki çalışma dizinini geri yüklemeyi ve daha fazlasını mümkün kılar. Metin düzenleyicide, kullanıcının açtığı en son beş dosyanın listesini depoluyorum. Böylece, bu dosyalara tekrar erişim kolaylaşıyor.

Aşağıdaki kod örneğinde bir dosya tanıtıcısının ve dizin tutma yerinin saklanması ve alınması gösterilmektedir. Glitch'te uygulamayı görebilirsiniz. (Kısa olması 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 tanıtıcıları ve izinleri

İzinler şu anda oturumlar arasında kalıcı olmadığından, kullanıcının queryPermission() kullanarak dosyaya veya dizine izin verip vermediğini doğrulamanız gerekir. Henüz göndermediyse requestPermission() adlı iş ortağını arayarak (yeniden) istekte bulunun. Bu işlem dosya ve dizin işleyicilerinde de aynı şekilde çalışır. Sırasıyla fileOrDirectoryHandle.requestPermission(descriptor) veya fileOrDirectoryHandle.queryPermission(descriptor) çalıştırmanız gerekir.

Metin düzenleyicide, kullanıcının zaten izin verip vermediğini ve gerekirse istekte bulunup bulunmadığını kontrol eden 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 yazma izni isteyerek izin istemlerinin sayısını azalttım. Kullanıcı dosyayı açarken bir istem görüyor ve hem okuma hem de yazma izni veriyor.

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

Bir dizindeki tüm dosyaları numaralandırmak için showDirectoryPicker() çağrısı yapın. Kullanıcı, seçicide bir dizin seçer. Bu dizinden sonra, dizin dosyalarını numaralandırmanı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 { mode: 'readwrite' } öğesini bu yönteme iletebilirsiniz.

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

Ek olarak, örneğin tek tek dosya boyutlarını elde etmek için her bir dosyaya getFile() aracılığıyla erişmeniz gerekirse await her sonuç için sırayla kullanmayın. Bunun yerine, tüm dosyaları paralel olarak (ör. Promise.all()) işleyin.

const butDir = document.getElementById('butDirectory');
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 klasörlere erişme

Bir dizinde, getFileHandle() veya sırasıyla getDirectoryHandle() yöntemini kullanarak dosya ve klasör oluşturabilir ya da dosyalara erişebilirsiniz. Anahtarı create ve boole değeri true ya da false olan isteğe bağlı bir options nesnesini geçirerek yeni bir dosya veya klasörün yoksa 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 });

Dizindeki bir öğ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 bir ş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 içerilen dosya ve klasörleri removeEntry() yöntemini kullanarak silebilirsiniz. Klasörlerde silme işlemi isteğe bağlı olarak yinelemeli olabilir ve tüm alt klasörler ile içindeki dosyaları da içerebilir.

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

Bir dosyayı veya klasörü doğrudan silme

Bir dosyaya veya dizin işleyiciye erişiminiz varsa kaldırmak için FileSystemFileHandle veya FileSystemDirectoryHandle üzerinde remove() numarasını arayın.

// 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ünden move() çağrısı yapı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. Birincisi, yeni ada sahip bir dize veya hedef klasör için bir FileSystemDirectoryHandle olabilir. İkinci örnekte isteğe bağlı ikinci parametre, yeni ada sahip bir dizedir. Bu nedenle, taşıma ve yeniden adlandırma tek bir adımda gerçekleştirilebilir.

// 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 özelliği

HTML Sürükle ve Bırak arayüzleri, web uygulamalarının bir web sayfasındaki sürüklenip 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şleri ve dizin girişleriyle ilişkilendirilir. DataTransferItem.getAsFileSystemHandle() yöntemi, sürüklenen öğe bir dosyaysa FileSystemFileHandle nesnesiyle sözü ve sürüklenen öğe bir dizinse FileSystemDirectoryHandle nesnesi içeren bir söz döndürür. Aşağıdaki girişte bu uygulama gösterilmektedir. Sürükle ve Bırak arayüzünün DataTransferItem.kind hem dosyalar hem de dizinler için "file", File System Access API'nin FileSystemHandle.kind ise dosyalar için "file", dizinler için "directory" değerindedir.

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 sayfa kaynağına özel olan bir depolama uç noktasıdır. Tarayıcılar genellikle bu kaynak özel dosya sisteminin içeriğini bir yerde diske tutarak bu uygulamayı uygulasa da, içeriklerin kullanıcı tarafından kolayca erişilebilir olması gerekmez. Benzer şekilde, kaynak özel dosya sisteminin alt adlarıyla eşleşen adlara sahip dosya veya dizinlerin olması gerekmez. Tarayıcı, kaynak özel bir dosya sistemi olduğu için dahili olarak dosyalar varmış gibi görünse de, tarayıcı bu "dosyaları" bir veritabanında veya başka herhangi bir veri yapısında depolayabilir. Esas olarak, bu API'yi kullanıyorsanız oluşturulan dosyaların sabit diskin bir yerinde bire bir eşleştirilmiş dosyaları bulmayı beklemeyin. Kök FileSystemDirectoryHandle öğesine erişim elde ettikten sonra kaynak özel dosya sisteminde her zamanki gibi çalışabilirsiniz.

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

  • 86
  • 86
  • 111
  • 15,2

Kaynak

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

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

// (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öntemlerinin tümünü çoklu doldurmak mümkün değildir.

  • showOpenFilePicker() yöntemi, bir <input type="file"> öğesiyle yaklaştırılabilir.
  • showSaveFilePicker() yöntemi, bir <a download="file_name"> öğesiyle simüle edilebilir. Bununla birlikte, bu yöntem programatik indirme işlemini tetikler ve mevcut dosyaların üzerine yazılmasına izin vermez.
  • showDirectoryPicker() yöntemi, standart olmayan <input type="file" webkitdirectory> öğesiyle bir şekilde emüle edilebilir.

Mümkün olan her yerde File System Access API'yi kullanan ve diğer her durumda bir sonraki en iyi seçenekleri kullanan browser-fs-access adında bir kitaplık geliştirdik.

Güvenlik ve izinler

Chrome ekibi, File System Access API'yi, kullanıcı denetimi, şeffaflık ve kullanıcı ergonomisi de dahil olmak üzere Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme bölümünde tanımlanan temel ilkeleri kullanarak tasarlamış ve uygulamıştır.

Dosya açma veya yeni bir dosya kaydetme

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

Kullanıcı bir dosyayı açarken dosya seçici aracılığıyla bir dosyayı veya dizini okuma izni verir. Açık dosya seçici yalnızca güvenli bir bağlamdan sunulduğunda bir kullanıcı hareketiyle gösterilebilir. Kullanıcılar fikirlerini değiştirirse dosya seçicideki seçimi iptal edebilir ve 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 kaydetme seçiciyi gösterir. Bu, kullanıcının yeni dosyanın adını ve konumunu belirtmesine olanak tanır. Cihaza yeni bir dosya kaydettiğinden (mevcut bir dosyanın üzerine yazılmasına karşın) dosya seçici, uygulamaya dosyaya yazma izni verir.

Kısıtlanmış klasörler

Kullanıcıların ve verilerinin korunmasına yardımcı olmak için tarayıcı, kullanıcının Windows gibi temel işletim sistemi klasörleri, macOS Kitaplık klasörleri gibi belirli klasörlere kaydetme özelliğini sınırlandırabilir. Bu durumda, tarayıcı bir istem görüntüler ve kullanıcıdan farklı bir klasör seçmesini ister.

Mevcut bir dosyayı veya dizini değiştirme

Bir web uygulaması, kullanıcıdan açık izin almadan diskteki bir dosyayı değiştiremez.

İzin istemi

Bir kişi daha önce okuma erişimi verdiği bir dosyada yapılan değişiklikleri kaydetmek isterse tarayıcı, sitenin diske değişiklik yazması için izin isteyen bir izin istemi görüntüler. İzin isteği yalnızca bir kullanıcı hareketiyle (örneğin, Kaydet düğmesinin tıklanması) tetiklenebilir.

Dosya kaydedilmeden ö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 çok dosyayı düzenleyen bir web uygulaması da açılış sırasında değişiklikleri kaydetme izni isteyebilir.

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

Şeffaflık

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

Bir kullanıcı yerel bir dosyayı kaydetmesi için bir web uygulamasına izin verdiğinde, tarayıcı URL ç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ı isterse bu erişimi kolayca iptal edebilir.

İzin kalıcılığı

Web uygulaması, kaynağının tüm sekmeleri kapatılana kadar sormadan dosyada yapılan değişiklikleri kaydetmeye devam edebilir. Bir sekme kapatıldığında site tüm erişimi kaybeder. Kullanıcının web uygulamasını tekrar kullandığında dosyalara erişmesi tekrar istenir.

Geri bildirim

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

Bize API tasarımı hakkında bilgi verin

API'de beklediğiniz gibi çalışmayan bir durum mu var? Fikrinizi uygulamak için gereken yöntem veya özellikler eksik mi? Güvenlik modeliyle ilgili bir sorunuz veya yorumunuz mu var?

Uygulamayla ilgili bir sorun mu var?

Chrome'un uygulamasında bir hata buldunuz mu? Yoksa uygulama, spesifikasyondan farklı mı?

  • https://new.crbug.com adresinden hata bildiriminde bulunun. Mümkün olduğunca fazla ayrıntı eklediğinizden, yeniden oluşturma için basit talimatları eklediğinizden ve Bileşenler'i Blink>Storage>FileSystem olarak ayarladığınızdan emin olun. Glitch, hızlı ve kolay yeniden oluşturmalar paylaşmak için idealdir.

API'yi kullanmayı mı planlıyorsunuz?

Sitenizde File System Access API'yi kullanmayı mı planlıyorsunuz? Herkese açık desteğiniz, özellikleri önceliklendirmemize yardımcı olur ve diğer tarayıcı satıcılarına onları desteklemenin ne kadar kritik olduğunu gösterir.

Faydalı bağlantılar

Teşekkür

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