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.

Yayınlanma tarihi: 19 Ağustos 2024

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

Daha önce dosya okuma ve yazma işlemleriyle çalıştıysanız paylaşacağım bilgilerin çoğu size tanıdık gelecektir. Ancak tüm sistemler aynı olmadığından yine de okumanızı öneririz.

Dosya Sistemi Erişim API'si, Windows, macOS, ChromeOS, Linux ve Android'deki çoğu Chromium tarayıcıda desteklenir. Brave, şu anda yalnızca bir bayrak arkasında kullanılabilen önemli bir istisnadır.

File System Access API'yi kullanma

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

Tarayıcı desteği

Browser Support

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

Source

Özellik algılama

File System Access API'nin desteklenip desteklenmediğini öğrenmek için ilgilendiğiniz seçici yönteminin 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 nasıl çalıştığını görmek için metin düzenleyici demosuna göz atı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 isteyin.

File System Access API'nin giriş noktası window.showOpenFilePicker()'dir. Bu işlev çağrıldığında bir dosya seçici iletişim kutusu gösterilir ve kullanıcıdan bir dosya seçmesi istenir. Kullanıcılar bir dosya seçtikten sonra API, dosya işleyicileri dizisini döndürür. İsteğe bağlı bir 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ürleri seçmesine izin verebilirsiniz. Herhangi bir seçenek belirtilmediğinde, dosya seçici 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 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çtiğinde showOpenFilePicker(), bu durumda dosya ile etkileşim kurmak için gereken özellikleri ve yöntemleri içeren bir FileSystemFileHandle ile tek öğeli bir dizi olmak üzere bir dizi tutma yeri döndürür.

Dosya tutma yerine daha sonra kullanılabilecek bir referans tutmak yararlıdır. Dosyadaki değişiklikleri kaydetmek veya başka dosya işlemleri yapmak için bu izin gerekir.

Dosya sisteminden dosya okuma

Artık bir dosyanın tanıtıcısına sahip olduğunuz için dosyanın özelliklerini alabilir veya dosyanın kendisine erişebilirsiniz. Şimdilik içeriğini okuyacağım. handle.getFile() işlevini çağırmak, blob içeren bir File nesnesi döndürür. Blob'dan 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, diskteki temel dosya değişmediği sürece yalnızca 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.

Özet

Kullanıcılar düğmesini tıkladığında tarayıcıda dosya seçici gösterilir. Dosya seçildikten sonra uygulama, içeriği okuyup <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ı kaydetmek için iki yöntem vardır: Kaydet ve Farklı Kaydet. Kaydet daha önce alınan dosya tutamacını kullanarak değişiklikleri orijinal dosyaya geri yazar. Ancak Farklı Kaydet yeni bir dosya oluşturduğundan yeni bir dosya tutacağı gerekir.

Yeni dosya oluşturma

Bir dosyayı kaydetmek için showSaveFilePicker() işlevini çağırın. Bu işlev, dosya seçiciyi "kaydet" 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 .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;
}

Diskteki değişiklikleri kaydetme

Değişiklikleri dosyaya kaydetmeyle ilgili tüm kodları GitHub'daki metin düzenleyici demomda bulabilirsiniz. Temel dosya sistemi etkileşimleri fs-helpers.js içinde yer alır. En basit haliyle süreç aşağıdaki kod gibi görünür. Her adımı açıklayarak ilerleyeceğim.

// 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 yazmak için WritableStream alt sınıfı olan bir FileSystemWritableFileStream nesnesi kullanılır. Dosya işleyici nesnesinde createWritable() işlevini çağırarak akışı oluşturun. createWritable() çağrıldığında tarayıcı, kullanıcının dosyaya yazma izni verip vermediğini kontrol eder. Yazma izni verilmemişse tarayıcı, kullanıcıdan izin ister. İzin verilmezse createWritable() bir DOMException oluşturur ve uygulama dosyaya yazamaz. Metin düzenleyicide, DOMException nesneleri saveFile() yöntemiyle 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 dosyaya yönlendirebilirsiniz:

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, akış içinde seek() veya truncate() simgesini tıklayarak dosyayı belirli bir konumda güncelleyebilir ya da yeniden boyutlandırabilirsiniz.

Ö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 varsayılan dosya adını önermek isteyebilir. Bunu, suggestedName seçeneği kapsamında bir showSaveFilePicker özelliği ileterek 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. Bir metin düzenleyici oluşturuyorsanız dosya kaydetme veya dosya açma iletişim kutusunu varsayılan documents klasöründe başlatmak isteyebilirsiniz. Bir resim düzenleyici için ise varsayılan pictures klasöründe başlatmak isteyebilirsiniz. startIn özelliğini showSaveFilePicker, showDirectoryPicker() veya showOpenFilePicker yöntemlerine aşağıdaki gibi 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 görüntülerin genellikle depolandığı dizin.
  • videos: Videoların veya filmlerin genellikle depolandığı dizin.

Bilinen sistem dizinlerinin yanı sıra, mevcut bir dosya veya dizin tutamacını da startIn için değer olarak 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

Uygulamalarda bazen 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 izin verebilir. Varsayılan olarak, her dosya seçici son hatırlanan konumda açılırdı. Her seçici türü için id değerlerini depolayarak bu durumu önleyebilirsiniz. Bir id belirtilirse dosya seçici uygulaması, bu 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',
});

IndexedDB'de dosya tutmaçlarını veya dizin tutmaçlarını depolama

Dosya tutamaçları ve dizin tutamaçları serileştirilebilir. Bu nedenle, bir dosya veya dizin tutamacını IndexedDB'ye kaydedebilir ya da aynı üst düzey kaynaklar arasında göndermek için postMessage() işlevini çağırabilirsiniz.

Dosya veya dizin tutmaçlarını IndexedDB'ye kaydetmek, durumu depolayabileceğiniz veya kullanıcının hangi dosyalar ya da dizinler üzerinde çalıştığını 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çmayı teklif edebilir, önceki çalışma dizinini geri yükleyebilir ve daha fazlasını yapabilirsiniz. Metin düzenleyicide, kullanıcının açtığı en son beş dosyanın listesini saklıyorum. Böylece bu dosyalara tekrar erişilebiliyor.

Aşağıdaki kod örneğinde, dosya tutma biriminin ve dizin tutma biriminin depolanması ve alınması gösterilmektedir. Bu özelliği Glitch'te kullanırken 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 tutamaçları ve izinleri

İzinler oturumlar arasında her zaman kalıcı olmadığından kullanıcının queryPermission() kullanarak dosyaya veya dizine izin verip vermediğini doğrulamanız gerekir. Bu durumda, requestPermission() numaralı telefonu arayarak (yeniden) isteyin. Bu durum, dosya ve dizin tutma işlemleri için de geçerlidir. Sırasıyla fileOrDirectoryHandle.requestPermission(descriptor) veya fileOrDirectoryHandle.queryPermission(descriptor) komutunu çalıştırmanız gerekir.

Metin düzenleyicide, kullanıcının izni daha önce 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 tek bir istem görür ve hem okuma hem de yazma izni verir.

Bir dizini açma ve içeriğini listeleme

Bir dizindeki tüm dosyaları listelemek için showDirectoryPicker() işlevini çağırın. Kullanıcı, seçicide bir dizin seçer. Ardından, dizinin dosyalarını numaralandırmanıza ve 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);
  }
});

Ayrıca, örneğin tek tek dosya boyutlarını almak için her bir dosyaya getFile() kullanarak erişmeniz gerekiyorsa her sonuçta sırayla await kullanmayın. Bunun yerine, örneğin Promise.all() kullanarak tüm dosyaları paralel olarak işleyin.

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

Bir dizinden getFileHandle() veya getDirectoryHandle() yöntemini kullanarak dosya ve klasör oluşturabilir ya da bunlara erişebilirsiniz. options anahtarına sahip isteğe bağlı bir create nesnesi ve true veya false boole değeri ileterek, yeni bir dosya ya da klasörün mevcut olmaması durumunda 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 çözme

Bir dizindeki dosyalarla 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ümleme için öğe, dizinin doğrudan veya dolaylı 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şiminiz varsa içerdiği dosyaları ve klasörleri removeEntry() yöntemiyle silebilirsiniz. Klasörler için silme işlemi isteğe bağlı olarak yinelemeli olabilir ve tüm alt klasörleri ve içerdiği dosyaları kapsayabilir.

// 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 tanıtıcısına erişiminiz varsa FileSystemFileHandle üzerinde remove() işlevini çağırarak ya da FileSystemDirectoryHandle işlevini kullanarak kaldırın.

// 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, move() arayüzünde FileSystemHandle ç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. Birincisi, 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 tek 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ükleyip bırakarak entegrasyon

HTML sürükle ve bırakma arayüzleri, web uygulamalarının bir web sayfasında sürüklenip bırakılan dosyaları kabul etmesini sağlar. Sürükleyip bırakma 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 söz, sürüklenen öğe bir dizinse FileSystemDirectoryHandle nesnesi içeren bir söz döndürür. Aşağıdaki listede bu durum gösterilmektedir. Sürükle ve bırak arayüzünün DataTransferItem.kind simgesinin hem dosyalar hem de dizinler için, File System Access API'nin FileSystemHandle.kind simgesinin ise dosyalar için "file", dizinler için "directory" olduğunu unutmayın."file"

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 olan bir depolama uç noktasıdır. Tarayıcılar genellikle bu özelliği, bu kaynak özel dosya sisteminin içeriğini bir yerde diske kaydederek uygular. Ancak içeriğin kullanıcı tarafından erişilebilir olması amaçlanmamıştır. Benzer şekilde, kaynak özel dosya sisteminin çocuklarının adlarıyla eşleşen adlara sahip dosyaların veya dizinlerin varlığı beklenmez. Tarayıcı, dosyalar varmış gibi görünmesine neden olsa da bu, kaynak özel dosya sistemi olduğundan tarayıcı bu "dosyaları" dahili olarak 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şmesini beklemeyin. Kök FileSystemDirectoryHandle erişiminiz olduğunda, 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 });

Browser Support

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

Source

Performans için optimize edilmiş dosyalara, kaynak özel 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, dosya erişimini basitleştirmek için kaynak özel dosya sisteminde ek bir yöntem bulunur: createSyncAccessHandle() (eşzamanlı okuma ve yazma işlemleri için). FileSystemFileHandle üzerinde kullanıma sunulur ancak yalnızca Web Workers'da kullanılabilir.

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

Polyfilling

File System Access API yöntemlerinin tamamen polyfill'i mümkün değildir.

  • showOpenFilePicker() yöntemi, <input type="file"> öğesiyle yaklaşık olarak hesaplanabilir.
  • showSaveFilePicker() yöntemi, <a download="file_name"> öğesiyle simüle edilebilir ancak bu, programatik bir 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 ölçüde taklit edilebilir.

Mümkün olan her yerde File System Access API'yi kullanan ve diğer tüm durumlarda bir sonraki en iyi seçeneklere geri dönen browser-fs-access adlı bir kitaplık geliştirdik.

Güvenlik ve izinler

Chrome Ekibi, kullanıcı kontrolü, şeffaflık ve kullanıcı ergonomisi gibi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme'de tanımlanan temel ilkeleri kullanarak File System Access API'yi tasarlayıp uyguladı.

Dosya açma veya yeni dosya kaydetme

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

Kullanıcı, bir dosyayı açarken dosya seçiciyi kullanarak dosya veya dizini okuma izni verir. Açık dosya seçici, yalnızca güvenli bir bağlamdan sunulduğunda 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.
Dosyayı diske kaydetmek için kullanılan bir dosya seçici.

Benzer şekilde, bir web uygulaması yeni bir dosya kaydetmek istediğinde tarayıcı, dosyayı kaydetme seçiciyi göstererek kullanıcının yeni dosyanın adını ve konumunu belirtmesine olanak tanır. Cihaza yeni bir dosya kaydedildiği için (mevcut bir dosyanın üzerine yazılmadığı için) dosya seçici, uygulamaya dosyaya yazma izni verir.

Kısıtlanmış klasörler

Tarayıcı, kullanıcıları ve verilerini korumak 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

Bir web uygulaması, 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 dosyada değişiklikleri kaydetmek isterse tarayıcı, siteye değişiklikleri diske yazma izni isteyen bir izin istemi gösterir. İzin isteği yalnızca bir kullanıcı hareketiyle (ör. Kaydet düğmesini tıklayarak) tetiklenebilir.

Dosya kaydedilmeden önce izin istemi gösterilir.
Tarayıcıya mevcut bir dosyada yazma izni verilmeden önce kullanıcılara gösterilen istem.

Alternatif olarak, birden fazla dosyayı düzenleyen bir web uygulaması (ör. IDE) da açma sırasında değişiklikleri kaydetme izni isteyebilir.

Kullanıcı İptal'i seçerse ve yazma erişimi vermezse web uygulaması, yerel dosyada yapılan değişiklikleri kaydedemez. Kullanıcıya verilerini kaydetmesi için alternatif bir yöntem sunulmalıdır. Örneğin, dosyayı"indirme" veya verileri buluta kaydetme yolu sağlanmalıdır.

Şeffaflık

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

Bir kullanıcı, 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-over açılır. Kullanıcı, dilediği zaman bu erişimi iptal edebilir.

İzin kalıcılığı

Web uygulaması, kaynağına ait tüm sekmeler kapatılana kadar dosyada yapılan değişiklikleri istemde bulunmadan 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 istemde bulunulur.

Geri bildirim

File System Access API ile ilgili deneyimlerinizi bizimle paylaşmanızı istiyoruz.

API tasarımı hakkında bilgi verin

API ile ilgili beklentilerinizi karşılamayan bir durum var mı? Yoksa fikrinizi uygulamak için eksik yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var?

Uygulamayla ilgili sorun mu var?

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 üretme talimatları eklediğinizden emin olun ve Bileşenler'i Blink>Storage>FileSystem olarak ayarlayın.

API'yi kullanmayı mı planlıyorsunuz?

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

Faydalı bağlantılar

Teşekkür

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