File System Access API: menyederhanakan akses ke file lokal

File System Access API memungkinkan aplikasi web membaca atau menyimpan perubahan secara langsung ke file dan folder di perangkat pengguna.

Apa yang dimaksud dengan File System Access API?

File System Access API memungkinkan developer membuat aplikasi web canggih yang berinteraksi dengan file di perangkat lokal pengguna, seperti IDE, editor foto dan video, editor teks, dan lainnya. Setelah pengguna memberikan akses aplikasi web, API ini memungkinkan mereka membaca atau menyimpan perubahan secara langsung ke file dan folder di perangkat pengguna. Selain membaca dan menulis file, File System Access API memberikan kemampuan untuk membuka direktori dan mengenumerasi kontennya.

Jika Anda pernah membaca dan menulis file sebelumnya, sebagian besar hal yang akan saya bagikan akan terlihat familiar bagi Anda. Sebaiknya Anda tetap membacanya, karena tidak semua sistem sama.

File System Access API didukung di sebagian besar browser Chromium di Windows, macOS, ChromeOS, dan Linux. Pengecualiannya adalah Brave, yang saat ini hanya tersedia di belakang flag. Dukungan untuk Android sedang dikerjakan dalam konteks crbug.com/1011535.

Menggunakan File System Access API

Untuk menunjukkan keandalan dan kegunaan File System Access API, saya menulis satu file editor teks. Dengan ini, Anda dapat membuka file teks, mengeditnya, menyimpan perubahan kembali ke disk, atau memulai file baru dan menyimpan perubahan ke disk. Ini bukan hal yang mewah, tetapi cukup untuk membantu Anda memahami konsepnya.

Dukungan browser

Dukungan Browser

  • Chrome: 86.
  • Edge: 86.
  • Firefox: tidak didukung.x
  • Safari: tidak didukung.

Sumber

Deteksi fitur

Untuk mengetahui apakah File System Access API didukung, periksa apakah metode pemilih yang Anda minati ada.

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

Coba

Lihat cara kerja File System Access API dalam demo editor teks.

Membaca file dari sistem file lokal

Kasus penggunaan pertama yang ingin saya tangani adalah meminta pengguna memilih file, lalu membuka dan membaca file tersebut dari disk.

Meminta pengguna untuk memilih file yang akan dibaca

Titik entri ke File System Access API adalah window.showOpenFilePicker(). Saat dipanggil, dialog pemilih file akan ditampilkan dan pengguna diminta memilih file. Setelah pengguna memilih file, API akan menampilkan array handle file. Parameter options opsional memungkinkan Anda memengaruhi perilaku pemilih file, misalnya, dengan memungkinkan pengguna memilih beberapa file, atau direktori, atau jenis file yang berbeda. Tanpa opsi yang ditentukan, pemilih file memungkinkan pengguna memilih satu file. Hal ini cocok untuk editor teks.

Seperti banyak API canggih lainnya, memanggil showOpenFilePicker() harus dilakukan dalam konteks aman, dan harus dipanggil dari dalam gestur pengguna.

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

Setelah pengguna memilih file, showOpenFilePicker() akan menampilkan array nama sebutan, dalam hal ini array satu elemen dengan satu FileSystemFileHandle yang berisi properti dan metode yang diperlukan untuk berinteraksi dengan file.

Sebaiknya simpan referensi ke handle file agar dapat digunakan nanti. Anda harus menyimpan perubahan pada file, atau melakukan operasi file lainnya.

Membaca file dari sistem file

Setelah memiliki handle ke file, Anda bisa mendapatkan properti file, atau mengakses file itu sendiri. Untuk saat ini, saya akan membaca kontennya. Memanggil handle.getFile() akan menampilkan objek File, yang berisi blob. Untuk mendapatkan data dari blob, panggil salah satu metodenya, (slice(), stream(), text(), atau arrayBuffer()).

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

Objek File yang ditampilkan oleh FileSystemFileHandle.getFile() hanya dapat dibaca selama file dasar di disk belum berubah. Jika file pada disk diubah, objek File menjadi tidak dapat dibaca dan Anda harus memanggil getFile() lagi untuk mendapatkan objek File baru agar dapat membaca data yang diubah.

Menggabungkan semuanya

Saat pengguna mengklik tombol Open, browser akan menampilkan pemilih file. Setelah pengguna memilih file, aplikasi akan membaca konten dan memasukkannya ke dalam <textarea>.

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

Menulis file ke sistem file lokal

Di editor teks, ada dua cara untuk menyimpan file: Simpan, dan Simpan Sebagai. Simpan menulis perubahan kembali ke file asli menggunakan handle file yang diambil sebelumnya. Namun, Simpan Sebagai akan membuat file baru, sehingga memerlukan handle file baru.

Membuat file baru

Untuk menyimpan file, panggil showSaveFilePicker(), yang menampilkan pemilih file dalam mode "save", yang memungkinkan pengguna memilih file baru yang ingin mereka gunakan untuk disimpan. Untuk editor teks, saya juga ingin editor tersebut otomatis menambahkan ekstensi .txt, jadi saya memberikan beberapa parameter tambahan.

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

Menyimpan perubahan ke disk

Anda dapat menemukan semua kode untuk menyimpan perubahan pada file dalam demo editor teks saya di GitHub. Interaksi sistem file inti berada di fs-helpers.js. Pada dasarnya, prosesnya terlihat seperti kode berikut. Saya akan menjelaskan setiap langkahnya.

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

Menulis data ke disk menggunakan objek FileSystemWritableFileStream, yang merupakan subclass WritableStream. Buat streaming dengan memanggil createWritable() pada objek handle file. Saat createWritable() dipanggil, browser akan memeriksa terlebih dahulu apakah pengguna telah memberikan izin tulis ke file. Jika izin untuk menulis belum diberikan, browser akan meminta izin kepada pengguna. Jika izin tidak diberikan, createWritable() akan menampilkan DOMException, dan aplikasi tidak akan dapat menulis ke file. Di editor teks, objek DOMException ditangani dalam metode saveFile().

Metode write() mengambil string, yang diperlukan oleh editor teks. Namun, BufferSource atau Blob juga dapat digunakan. Misalnya, Anda dapat menyalurkan streaming langsung ke file tersebut:

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.
}

Anda juga dapat seek(), atau truncate() dalam streaming untuk memperbarui file pada posisi tertentu, atau mengubah ukuran file.

Menentukan nama file dan direktori awal yang disarankan

Dalam banyak kasus, Anda mungkin ingin aplikasi menyarankan nama file atau lokasi default. Misalnya, editor teks mungkin ingin menyarankan nama file default Untitled Text.txt, bukan Untitled. Anda dapat melakukannya dengan meneruskan properti suggestedName sebagai bagian dari opsi showSaveFilePicker.

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

Hal yang sama berlaku untuk direktori awal default. Jika membuat editor teks, sebaiknya mulai dialog simpan file atau buka file di folder documents default, sedangkan untuk editor gambar, sebaiknya mulai di folder pictures default. Anda dapat menyarankan direktori awal default dengan meneruskan properti startIn ke metode showSaveFilePicker, showDirectoryPicker(), atau showOpenFilePicker seperti ini.

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

Daftar direktori sistem yang terkenal adalah:

  • desktop: Direktori desktop pengguna, jika ada.
  • documents: Direktori tempat dokumen yang dibuat oleh pengguna biasanya disimpan.
  • downloads: Direktori tempat file yang didownload biasanya disimpan.
  • music: Direktori tempat file audio biasanya disimpan.
  • pictures: Direktori tempat foto dan gambar diam lainnya biasanya disimpan.
  • videos: Direktori tempat video atau film biasanya disimpan.

Selain direktori sistem yang dikenal, Anda juga dapat meneruskan file atau handle direktori yang ada sebagai nilai untuk startIn. Dialog kemudian akan terbuka di direktori yang sama.

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

Menentukan tujuan berbagai pemilih file

Terkadang aplikasi memiliki pemilih yang berbeda untuk tujuan yang berbeda. Misalnya, editor teks lengkap dapat memungkinkan pengguna membuka file teks, tetapi juga mengimpor gambar. Secara default, setiap pemilih file akan terbuka di lokasi yang terakhir diingat. Anda dapat mengakalinya dengan menyimpan nilai id untuk setiap jenis pemilih. Jika id ditentukan, implementasi pemilih file akan mengingat direktori terakhir yang digunakan secara terpisah untuk id tersebut.

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

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

Menyimpan handle file atau handle direktori di IndexedDB

ID file dan ID direktori dapat diserialisasi, yang berarti Anda dapat menyimpan ID file atau direktori ke IndexedDB, atau memanggil postMessage() untuk mengirimnya di antara origin tingkat atas yang sama.

Menyimpan handle file atau direktori ke IndexedDB berarti Anda dapat menyimpan status, atau mengingat file atau direktori yang sedang dikerjakan pengguna. Hal ini memungkinkan Anda menyimpan daftar file yang baru saja dibuka atau diedit, menawarkan untuk membuka kembali file terakhir saat aplikasi dibuka, memulihkan direktori kerja sebelumnya, dan lainnya. Di editor teks, saya menyimpan daftar lima file terbaru yang dibuka pengguna, sehingga file tersebut dapat diakses lagi.

Contoh kode berikut menunjukkan penyimpanan dan pengambilan handle file dan handle direktori. Anda dapat melihat cara kerjanya di Glitch. (Saya menggunakan library idb-keyval agar lebih ringkas.)

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

Izin dan nama sebutan file atau direktori yang disimpan

Karena izin tidak selalu dipertahankan di antara sesi, Anda harus memverifikasi apakah pengguna telah memberikan izin ke file atau direktori menggunakan queryPermission(). Jika belum, panggil requestPermission() untuk (meminta ulang) token. Cara kerjanya sama untuk nama sebutan file dan direktori. Anda harus menjalankan fileOrDirectoryHandle.requestPermission(descriptor) atau fileOrDirectoryHandle.queryPermission(descriptor).

Di editor teks, saya membuat metode verifyPermission() yang memeriksa apakah pengguna telah memberikan izin, dan jika diperlukan, membuat permintaan.

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;
}

Dengan meminta izin tulis dengan permintaan baca, saya mengurangi jumlah prompt izin; pengguna melihat satu perintah saat membuka file, dan memberikan izin untuk membaca dan menulis ke file.

Membuka direktori dan menghitung isinya

Untuk menghitung semua file dalam direktori, panggil showDirectoryPicker(). Pengguna memilih direktori di pemilih, setelah itu FileSystemDirectoryHandle ditampilkan, yang memungkinkan Anda menghitung dan mengakses file direktori. Secara default, Anda akan memiliki akses baca ke file dalam direktori, tetapi jika memerlukan akses tulis, Anda dapat meneruskan { mode: 'readwrite' } ke metode.

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

Jika Anda juga perlu mengakses setiap file menggunakan getFile() untuk, misalnya, mendapatkan ukuran file individual, jangan gunakan await pada setiap hasil secara berurutan, tetapi proses semua file secara paralel, misalnya, menggunakan Promise.all().

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

Membuat atau mengakses file dan folder di direktori

Dari direktori, Anda dapat membuat atau mengakses file dan folder menggunakan metode getFileHandle() atau getDirectoryHandle(). Dengan meneruskan objek options opsional dengan kunci create dan nilai boolean true atau false, Anda dapat menentukan apakah file atau folder baru harus dibuat jika tidak ada.

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

Menyelesaikan jalur item dalam direktori

Saat menangani file atau folder dalam direktori, akan berguna untuk me-resolve jalur item yang dimaksud. Hal ini dapat dilakukan dengan metode resolve() yang dinamai dengan tepat. Untuk me-resolve, item dapat berupa turunan langsung atau tidak langsung dari direktori.

// 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"]

Menghapus file dan folder di direktori

Jika telah memperoleh akses ke direktori, Anda dapat menghapus file dan folder yang ada dengan metode removeEntry(). Untuk folder, penghapusan dapat bersifat rekursif dan menyertakan semua subfolder dan file yang ada di dalamnya.

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

Menghapus file atau folder secara langsung

Jika Anda memiliki akses ke file atau handle direktori, panggil remove() di FileSystemFileHandle atau FileSystemDirectoryHandle untuk menghapusnya.

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

Mengganti nama dan memindahkan file dan folder

File dan folder dapat diganti namanya atau dipindahkan ke lokasi baru dengan memanggil move() pada antarmuka FileSystemHandle. FileSystemHandle memiliki antarmuka turunan FileSystemFileHandle dan FileSystemDirectoryHandle. Metode move() menggunakan satu atau dua parameter. Yang pertama dapat berupa string dengan nama baru atau FileSystemDirectoryHandle ke folder tujuan. Dalam kasus kedua, parameter kedua opsional adalah string dengan nama baru, sehingga pemindahan dan penggantian nama dapat terjadi dalam satu langkah.

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

Integrasi tarik lalu lepas

Antarmuka Tarik lalu Lepaskan HTML memungkinkan aplikasi web menerima file yang ditarik lalu dilepaskan di halaman web. Selama operasi tarik lalu lepas, file yang ditarik dan item direktori masing-masing akan dikaitkan dengan entri file dan entri direktori. Metode DataTransferItem.getAsFileSystemHandle() menampilkan promise dengan objek FileSystemFileHandle jika item yang ditarik adalah file, dan promise dengan objek FileSystemDirectoryHandle jika item yang ditarik adalah direktori. Listingan berikut menunjukkan cara kerjanya. Perlu diketahui bahwa antarmuka Tarik lalu Lepas DataTransferItem.kind adalah "file" untuk file dan direktori, sedangkan FileSystemHandle.kind File System Access API adalah "file" untuk file dan "directory" untuk direktori.

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}`);
    }
  }
});

Mengakses sistem file pribadi asal

Sistem file pribadi origin adalah endpoint penyimpanan yang, seperti namanya, bersifat pribadi untuk origin halaman. Meskipun browser biasanya menerapkannya dengan mempertahankan konten sistem file pribadi asal ini ke disk di suatu tempat, konten tersebut tidak dimaksudkan agar dapat diakses pengguna. Demikian pula, tidak ada ekspektasi bahwa file atau direktori dengan nama yang cocok dengan nama turunan sistem file pribadi asal ada. Meskipun browser mungkin membuat seolah-olah ada file, secara internal—karena ini adalah sistem file pribadi asal—browser mungkin menyimpan "file" ini dalam database atau struktur data lainnya. Pada dasarnya, jika Anda menggunakan API ini, jangan menemukan file yang dibuat cocok satu sama lain pada hard disk. Anda dapat beroperasi seperti biasa di sistem file pribadi asal setelah memiliki akses ke FileSystemDirectoryHandle root.

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

Mengakses file yang dioptimalkan untuk performa dari sistem file pribadi asal

Sistem file pribadi asal menyediakan akses opsional ke jenis file khusus yang sangat dioptimalkan untuk performa, misalnya, dengan menawarkan akses tulis eksklusif dan di tempat ke konten file. Di Chromium 102 dan yang lebih baru, ada metode tambahan pada sistem file pribadi origin untuk menyederhanakan akses file: createSyncAccessHandle() (untuk operasi baca dan tulis sinkron). Class ini diekspos pada FileSystemFileHandle, tetapi secara eksklusif di Web Worker.

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

Anda tidak dapat sepenuhnya melakukan polyfill pada metode File System Access API.

  • Metode showOpenFilePicker() dapat diperkirakan dengan elemen <input type="file">.
  • Metode showSaveFilePicker() dapat disimulasikan dengan elemen <a download="file_name">, walaupun hal ini memicu download terprogram dan tidak mengizinkan file yang ada ditimpa.
  • Metode showDirectoryPicker() dapat di-emulasi dengan elemen <input type="file" webkitdirectory> non-standar.

Kami telah mengembangkan library bernama browser-fs-access yang menggunakan File System Access API jika memungkinkan dan kembali ke opsi terbaik berikutnya dalam semua kasus lainnya.

Keamanan dan izin

Tim Chrome telah merancang dan menerapkan File System Access API menggunakan prinsip inti yang ditetapkan dalam Mengontrol Akses ke Fitur Platform Web yang Canggih, termasuk kontrol dan transparansi pengguna, serta ergonomi pengguna.

Membuka file atau menyimpan file baru

Pemilih file untuk membuka file guna dibaca
Pemilih file yang digunakan untuk membuka file yang ada untuk dibaca.

Saat membuka file, pengguna memberikan izin untuk membaca file atau direktori menggunakan pemilih file. Pemilih file terbuka hanya dapat ditampilkan menggunakan gestur pengguna saat ditayangkan dari konteks aman. Jika berubah pikiran, pengguna dapat membatalkan pilihan di pemilih file dan situs tidak mendapatkan akses ke apa pun. Perilaku ini sama dengan perilaku elemen <input type="file">.

Pemilih file untuk menyimpan file ke disk.
Pemilih file yang digunakan untuk menyimpan file ke disk.

Demikian pula, saat aplikasi web ingin menyimpan file baru, browser akan menampilkan pemilih file simpan, yang memungkinkan pengguna menentukan nama dan lokasi file baru. Karena menyimpan file baru ke perangkat (bukan menimpa file yang ada), pemilih file akan memberikan izin kepada aplikasi untuk menulis ke file.

Folder yang dibatasi

Untuk membantu melindungi pengguna dan data mereka, browser dapat membatasi kemampuan pengguna untuk menyimpan ke folder tertentu, misalnya, folder sistem operasi inti seperti Windows, folder Library macOS. Jika hal ini terjadi, browser akan menampilkan perintah dan meminta pengguna untuk memilih folder lain.

Mengubah file atau direktori yang ada

Aplikasi web tidak dapat mengubah file di disk tanpa mendapatkan izin eksplisit dari pengguna.

Dialog izin

Jika seseorang ingin menyimpan perubahan pada file yang sebelumnya telah dia izinkan untuk dibaca, browser akan menampilkan perintah izin, yang meminta izin agar situs dapat menulis perubahan ke disk. Permintaan izin hanya dapat dipicu oleh gestur pengguna, misalnya, dengan mengklik tombol Simpan.

Permintaan izin yang ditampilkan sebelum menyimpan file.
Perintah yang ditampilkan kepada pengguna sebelum browser diberi izin tulis pada file yang ada.

Atau, aplikasi web yang mengedit beberapa file, seperti IDE, juga dapat meminta izin untuk menyimpan perubahan pada saat dibuka.

Jika pengguna memilih Batal, dan tidak memberikan akses tulis, aplikasi web tidak dapat menyimpan perubahan pada file lokal. Harus menyediakan metode alternatif bagi pengguna untuk menyimpan datanya, misalnya dengan menyediakan cara untuk "mendownload" file atau menyimpan data ke cloud.

Transparansi

Ikon Omnibox
Ikon kolom URL yang menunjukkan bahwa pengguna telah memberikan izin ke situs untuk menyimpan ke file lokal.

Setelah pengguna memberikan izin ke aplikasi web untuk menyimpan file lokal, browser akan menampilkan ikon di kolom URL. Mengklik ikon akan membuka pop-over yang menampilkan daftar file yang aksesnya telah diberikan oleh pengguna. Pengguna selalu dapat mencabut akses tersebut jika mau.

Persistensi izin

Aplikasi web dapat terus menyimpan perubahan pada file tanpa meminta izin hingga semua tab untuk originnya ditutup. Setelah tab ditutup, situs akan kehilangan semua akses. Saat berikutnya pengguna menggunakan aplikasi web, mereka akan diminta lagi untuk mengakses file.

Masukan

Kami ingin mengetahui pengalaman Anda saat menggunakan File System Access API.

Ceritakan kepada kami tentang desain API

Apakah ada sesuatu tentang API yang tidak berfungsi seperti yang Anda harapkan? Atau apakah ada metode atau properti yang tidak ada yang Anda perlukan untuk menerapkan ide Anda? Ada pertanyaan atau komentar tentang model keamanan?

Ada masalah dengan implementasinya?

Apakah Anda menemukan bug pada penerapan Chrome? Atau apakah implementasinya berbeda dengan spesifikasi?

  • Laporkan bug di https://new.crbug.com. Pastikan untuk menyertakan detail sebanyak mungkin, petunjuk untuk mereproduksi, dan tetapkan Components ke Blink>Storage>FileSystem. Glitch sangat cocok untuk berbagi repro cepat.

Anda berencana menggunakan API?

Berencana untuk menggunakan File System Access API di situs Anda? Dukungan publik Anda membantu kami memprioritaskan fitur, dan menunjukkan kepada vendor browser lain betapa pentingnya mendukung fitur tersebut.

Link bermanfaat

Ucapan terima kasih

Spesifikasi File System Access API ditulis oleh Marijn Kruisselbrink.