Tarayıcı-fs erişim kitaplığı ile dosya ve dizinleri okuma ve yazma

Tarayıcılar, uzun zamandır dosya ve dizinlerle işlem yapmaktaydı. File API web uygulamalarında dosya nesnelerini temsil etmeye yönelik özellikler sunar, onları programlı bir şekilde seçme ve verilerine erişme. Ama daha yaklaştığınızda, ışıldayan her şey altın değildir.

Dosyalarla ilgilenmenin geleneksel yolu

Dosya açma

Geliştirici olarak şu adresteki dosyaları açabilir ve okuyabilirsiniz: <input type="file"> öğesine dokunun. En basit şekliyle, bir dosyayı açmak, aşağıdaki kod örneğine benzeyebilir. input nesnesi bir FileList sağlar, Bu örnek, aşağıdaki örnekte yalnızca bir File. File, belirli bir Blob türüdür, ve Blob'un yapabileceği herhangi bir bağlamda kullanılabilir.

const openFile = async () => {
  return new Promise((resolve) => {
    const input = document.createElement('input');
    input.type = 'file';
    input.addEventListener('change', () => {
      resolve(input.files[0]);
    });
    input.click();
  });
};

Dizinler açılıyor

Klasörleri (veya dizinleri) açmak için <input webkitdirectory> özelliğini gönderin. Bunun dışında diğer her şey yukarıdaki gibi çalışır. Tedarikçi firma tarafından öne çıkarılan adına rağmen webkitdirectory yalnızca Chromium ve WebKit tarayıcılarda değil, aynı zamanda Firefox'un yanı sıra EdgeHTML tabanlı Edge'de de kullanılabilir.

Dosyaları kaydetme (indirmek yerine)

Bir dosyayı kaydetmek için geleneksel olarak dosya indirme işlemi yeterlidir. Bu da Google Etiket Yöneticisi'nin <a download> özelliğini gönderin. Blob vererek, sabit reklamın href özelliğini şuradan alabileceğiniz bir blob: URL'sine ayarlayabilirsiniz: URL.createObjectURL() yöntemidir.

const saveFile = async (blob) => {
  const a = document.createElement('a');
  a.download = 'my-file.txt';
  a.href = URL.createObjectURL(blob);
  a.addEventListener('click', (e) => {
    setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
  });
  a.click();
};

Sorun

İndirme yaklaşımının en büyük dezavantajı, klasik bir indirme oluşturmanın open→edit→save (kaydet) akışı gerçekleşir, yani orijinal dosyanın üzerine yazmanın yolu yoktur. Bunun yerine, orijinal dosyanın yeni bir kopyasını elde edersiniz "kaydettiğinizde" işletim sisteminin varsayılan İndirilenler klasöründe bulabilirsiniz.

File System Access API

File System Access API, açma ve kaydetme işlemlerinin her ikisini de çok daha basit hale getirir. Ayrıca gerçek kaydetme olanağı da sunar. Yani bir dosyanın kaydedileceği yeri değil, mevcut bir dosyanın üzerine yazılır.

Dosya açma

File System Access API ile bir dosyanın açılması, window.showOpenFilePicker() yöntemine yapılan bir çağrıdır. Bu çağrı, getFile() yöntemini kullanarak gerçek File değerini alabileceğiniz bir dosya herkese açık kullanıcı adı döndürür.

const openFile = async () => {
  try {
    // Always returns an array.
    const [handle] = await window.showOpenFilePicker();
    return handle.getFile();
  } catch (err) {
    console.error(err.name, err.message);
  }
};

Dizinler açılıyor

Şu numarayı arayarak bir dizini açın: Dosya iletişim kutusunda dizinleri seçilebilir hale getiren window.showDirectoryPicker().

Dosyalar kaydediliyor

Dosyaları kaydetmek de benzer bir işlemdir. Bir dosya tanıtıcısından createWritable() üzerinden yazılabilir bir akış oluşturursunuz. akışın write() yöntemini çağırarak Blob verilerini yazıyorsunuz. ve son olarak close() yöntemini çağırarak akışı kapatıyorsunuz.

const saveFile = async (blob) => {
  try {
    const handle = await window.showSaveFilePicker({
      types: [{
        accept: {
          // Omitted
        },
      }],
    });
    const writable = await handle.createWritable();
    await writable.write(blob);
    await writable.close();
    return handle;
  } catch (err) {
    console.error(err.name, err.message);
  }
};

Tarayıcı-fs-access ile tanışın

File System Access API kadar her şeyi henüz geniş çapta kullanıma sunulmamıştır.

File System Access API için tarayıcı desteği tablosu. Tüm tarayıcılar &quot;desteklenmiyor&quot; şeklinde işaretlenmiş ya da &quot;bayrak arkasında&quot; gösterilebilir.
File System Access API için tarayıcı desteği tablosu. (Kaynak)

Bu nedenle File System Access API'yi ilerleyici bir geliştirme olarak görüyorum. Bu nedenle, tarayıcı desteklediğinde bunu kullanmak istiyorum, ve yoksa geleneksel yaklaşımı kullanın; tüm bunları yaparken kullanıcıyı, desteklenmeyen JavaScript kodunu gereksiz yere indirerek asla cezalandırmaz. browser-fs-access kitaplığımdaki görev, bu zorluğa yönelik cevabım.

Tasarım felsefesi

File System Access API hâlâ gelecekte değişebileceği için browser-fs-access API'si buna göre modellenmemiştir. Yani kitaplık bir çoklu dolgu değildir yerine midilli dolgu kullanılır. Uygulamanızı mümkün olduğunca küçük tutmak için ihtiyacınız olan her şeyi (statik veya dinamik olarak) sadece içe aktarabilirsiniz. Kullanılabilir yöntemler, en uygun şekilde adlandırılmıştır. fileOpen() directoryOpen() ve fileSave(). Kitaplık özelliği, File System Access API'nin desteklenip desteklenmediğini dahili olarak algılar. ardından ilgili kod yolunu içe aktarır.

browser-fs-access kitaplığını kullanma

Bu üç yöntem kolayca kullanılabilir. Uygulamanızda kabul edilen mimeTypes veya extensions dosyasını belirtip multiple işareti ayarlayabilirsiniz izin verebilirsiniz. Tüm ayrıntılar için bkz. browser-fs-access API dokümanlarına göz atın. Aşağıdaki kod örneğinde, resim dosyalarını nasıl açıp kaydedebileceğiniz gösterilmektedir.

// The imported methods will use the File
// System Access API or a fallback implementation.
import {
  fileOpen,
  directoryOpen,
  fileSave,
} from 'https://unpkg.com/browser-fs-access';

(async () => {
  // Open an image file.
  const blob = await fileOpen({
    mimeTypes: ['image/*'],
  });

  // Open multiple image files.
  const blobs = await fileOpen({
    mimeTypes: ['image/*'],
    multiple: true,
  });

  // Open all files in a directory,
  // recursively including subdirectories.
  const blobsInDirectory = await directoryOpen({
    recursive: true
  });

  // Save a file.
  await fileSave(blob, {
    fileName: 'Untitled.png',
  });
})();

Demo

Yukarıdaki kodun nasıl çalıştığını Glitch'teki demoda görebilirsiniz. Aynı şekilde kaynak kodu da burada bulunur. Güvenlik nedeniyle çapraz kaynak alt çerçevelerin bir dosya seçici göstermesine izin verilmez. demo bu makaleye yerleştirilemiyor.

Vahşi yaşamda browser-fs-access kitaplığı

Boş zamanlarımda, sosyal becerilerin yüklenebilir PWA Excalidraw olarak adlandırılan bir dizi elle çizilmiş gibi kolaylıkla çizimler yapmanızı sağlayan bir beyaz tahta aracı. Tamamen duyarlıdır ve küçük cep telefonlarından büyük ekranlı bilgisayarlara kadar pek çok farklı cihazda iyi bir şekilde çalışır. Bu, farklı platformlardaki dosyalarla ilgilenmesi gerektiği anlamına gelir. File System Access API'yi destekleyip desteklemedikleri. Bu nedenle tarayıcı fs-access kitaplığı için mükemmel bir adaydır.

Mesela iPhone'umda bir çizime başlıyorum. kaydedin (teknik olarak: Safari, File System Access API'yi desteklemediğinden indir) iPhone İndirilenler klasörüme, dosyayı masaüstümde aç (telefonumdan aktardıktan sonra) ve hatta yeni bir dosya olarak kaydedebilir, hatta bu dosyayı değişikliklerimle birlikte üzerine yazabilirim.

iPhone&#39;da bir Excalidraw çizimi.
File System Access API'nin desteklenmediği ancak bir dosyanın İndirilenler klasörüne kaydedilebileceği (indirilebileceği) bir iPhone'da Excalidraw çizimi başlatma.
ziyaret edin.
Masaüstündeki Chrome&#39;da değiştirilmiş Excalidraw çizimi.
File System Access API'nin desteklendiği ve böylece dosyaya API aracılığıyla erişilebildiği masaüstünde Excalidraw çizimini açma ve değiştirme.
ziyaret edin.
Değişiklikleri orijinal dosyanın üzerine yazmak.
Orijinal Excalidraw çizim dosyasındaki değişiklikleri yaparak orijinal dosyanın üzerine yazın. Tarayıcı, bunun uygun olup olmadığını soran bir iletişim kutusu gösteriyor.
ziyaret edin.
Yeni bir Excalidraw çizim dosyasındaki değişiklikler kaydediliyor.
Yeni bir Excalidraw dosyasında yapılan değişiklikler kaydediliyor. Orijinal dosyaya dokunulmaz.

Gerçek hayattan kod örneği

Aşağıda, Excalidraw'da kullanılan gerçek bir browser-fs-access örneğini görebilirsiniz. Bu alıntı, şuradan alındı: /src/data/json.ts. saveAsJSON() yönteminin bir dosya işleyiciyi veya null yöntemini browser-fs-access'e nasıl ilettiği özellikle ilgi çekicidir. fileSave() yöntemi kullanılır. Bu yöntem, herkese açık kullanıcı adı verildiğinde bu değerin üzerine yazılmasına neden olur. yeni bir dosyaya kaydedebilirsiniz.

export const saveAsJSON = async (
  elements: readonly ExcalidrawElement[],
  appState: AppState,
  fileHandle: any,
) => {
  const serialized = serializeAsJSON(elements, appState);
  const blob = new Blob([serialized], {
    type: "application/json",
  });
  const name = `${appState.name}.excalidraw`;
  (window as any).handle = await fileSave(
    blob,
    {
      fileName: name,
      description: "Excalidraw file",
      extensions: ["excalidraw"],
    },
    fileHandle || null,
  );
};

export const loadFromJSON = async () => {
  const blob = await fileOpen({
    description: "Excalidraw files",
    extensions: ["json", "excalidraw"],
    mimeTypes: ["application/json"],
  });
  return loadFromBlob(blob);
};

Kullanıcı arayüzü ile ilgili dikkat edilmesi gereken noktalar

İster Excalidraw'da ister uygulamanızda, kullanıcı arayüzü, tarayıcının destek durumuna uyum sağlamalıdır. File System Access API destekleniyorsa (if ('showOpenFilePicker' in window) {}) Kaydet düğmesine ek olarak bir Farklı Kaydet düğmesi de gösterebilirsiniz. Aşağıdaki ekran görüntülerinde, iPhone'da ve Chrome masaüstünde Excalidraw'ın duyarlı ana uygulama araç çubuğu arasındaki fark gösterilmektedir. iPhone'da Farklı Kaydet düğmesinin nasıl görünmediğine dikkat edin.

Yalnızca &quot;Kaydet&quot; seçeneği ile iPhone&#39;da Excalidraw uygulama araç çubuğu düğmesini tıklayın.
Yalnızca Kaydet düğmesine basarak iPhone'da uygulama araç çubuğunu Excalidraw.
ziyaret edin.
Chrome masaüstünde &quot;Kaydet&quot; seçeneği ile Excalidraw uygulama araç çubuğu &quot;Farklı Kaydet&quot; düğmesini tıklayın.
Excalidraw uygulama araç çubuğunu, Chrome'da Kaydet ve odaklanmış bir Farklı Kaydet düğmesiyle.

Sonuçlar

Sistem dosyalarıyla çalışma teknik olarak tüm modern tarayıcılarda çalışır. File System Access API'yi destekleyen tarayıcılarda (yalnızca indirilmesi değil) gerçek zamanlı olarak kaydedilmesi ve üzerine yazması için kullanıcılarınızın istedikleri yerde yeni dosyalar oluşturmalarını sağlayarak ve File System Access API'yi desteklemeyen tarayıcılarda çalışmaya devam edebilir. browser-fs-access hayatınızı kolaylaştırır gelişmiş geliştirmenin incelikleriyle başa çıkın ve kodunuzu mümkün olduğunca basitleştirin.

Teşekkür

Bu makale Joe Medley ve Kayce Bask. Excalidraw'a katkıda bulunanlara teşekkürler ve Çekme İsteklerimi incelemelerini rica ediyorum. Hero resim: Ilya Pavlov'un Unsplash.