İçeriğe atla
HexaTransfer
Bloga dön
Teknik incelemeler

Browser Depolama APIs için Dosya Transferi Applications

Leverage IndexedDB, File System Access API, ve Cache API için dosya transfer apps. Depolama limits, performance, ve browser compatibility.

Bir dosya transfer uygulaması için tarayıcı depolaması dört API arasında net biçimde bölünür: yapılandırılmış oturum ve parça meta verileri için IndexedDB (işlemsel, zaman uyumsuz, türlendirilmiş); kullanıcının diskinde birden fazla gigabaytlık dosyaları doğrudan okuyup yazmak için Dosya Sistemi Erişim API'si; HTTP yanıtları ve uygulama kabuğu varlıkları için Cache API; kota yönetimi ve kalıcılık ipuçları için Depolama Yöneticisi API'si. Korumalı yüksek performanslı G/Ç için Kaynak Özel Dosya Sistemi (OPFS) bu dördünün yanında yer alır. Doğrusunu seçmek önemlidir; çünkü limitler iOS Safari'de 1 GB'tan masaüstü Chrome'da "boş diskin %60'ına" kadar değişir ve yanlış seçim üretimde eninde sonunda QuotaExceededError hatası verir.

Her API'yi Doğru İşe Eşleştirme

Satır gibi görünen her şey için IndexedDB kullanın: yükleme oturumları, tamamlanmış parça indeksleri, paylaşım meta verileri, iptal belirteçleri. Zaman uyumsuz, işlemsel, indekslenebilir ve oturumlar arası sağlıklı çalışır.

Tüm dosyayı RAM'e yüklemeden baytları diske aktarmanız gerektiğinde — 500 MB'ın üzerindeki şifresi çözülmüş indirmeler için ideal — Dosya Sistemi Erişim API'sini kullanın. Chrome, Edge ve Opera tam desteği sağlar; Firefox ve Safari yalnızca showOpenFilePicker aracılığıyla salt okunur bir alt küme uygular.

Cache API'yi HTTP Response nesneleri için kullanın — JS paketiniz, CSS, ikonlar ve belki önbelleğe alınmış API yanıtları. Service Worker'larda fetch kesişimi için optimize edilmiştir.

OPFS'i (Dosya Sistemi Erişim API'sinin özel bir Kaynak-Özel dalı), çok gigabaytlık bir şifreleme geçişi sırasında yazma arabelleği gibi hızlı, korumalı, kullanıcı tarafından görünmeyen depolama istediğinizde kullanın. İkili blob'lar için IndexedDB'den bir büyüklük sırası yüksek disk verimi sağlar.

Pürüzler Olmadan IndexedDB

Ham IndexedDB'nin olaya dayalı API'si meşhur biçimde hantaldır. Jake Archibald'un idb paketini (sıkıştırılmış 1,5 KB) veya Dexie.js'yi (20 KB, daha zengin sorgu API'si) kullanın:

import { openDB } from 'idb';
const db = await openDB('transfers', 2, {
  upgrade(db, oldVersion) {
    if (oldVersion < 1) {
      const sessions = db.createObjectStore('sessions', { keyPath: 'id' });
      sessions.createIndex('by_expiry', 'expiresAt');
    }
    if (oldVersion < 2) {
      db.createObjectStore('chunks', { keyPath: ['sessionId', 'index'] });
    }
  }
});
await db.put('sessions', { id: 'abc', fileName: 'report.pdf', expiresAt: Date.now() + 86400000 });

Sürüm geçişleri upgrade geri çağrısında çalışır. v1'den v3'e atlayan kullanıcıların her iki adımı da alması için her zaman geçişleri oldVersion ile koruyun.

IndexedDB, yapılandırılmış klonlama yoluyla Blob'lar ve File referansları dahil çoğu veri biçimini işler. Bu, bir oturum kaydında File tanıtıcısını depolayabileceğiniz ve sekme yenilendikten sonra orijinal dosya baytlarını yeniden okuyabileceğiniz anlamına gelir — devam ettirilebilir yüklemeler için mükemmel.

Büyük İndirmeler için Dosya Sistemi Erişim API'si

API, tarayıcının kaydetme iletişim kutusuna yazılabilir bir akış iletmenizi sağlar:

const handle = await window.showSaveFilePicker({
  suggestedName: 'decrypted-archive.zip',
  types: [{ description: 'Zip', accept: { 'application/zip': ['.zip'] } }]
});
const writable = await handle.createWritable();
await decryptionStream.pipeTo(writable);

Baytlar JS yığınına hiç uğramadan doğrudan diske akar. Tarayıcıda 10 GB şifresi çözülmüş dosyayı kaydetmenin tek pratik yolu budur.

Firefox ve Safari için, indirme kullanıcı arayüzünü tetikleyen akışlı bir yanıt sentezlemek amacıyla bir Service Worker kullanan StreamSaver.js'ye geri düşün. Aynı ergonomi, biraz daha fazla hareketli parça.

Kalıcı dosya tanıtıcıları ayrıca bir uygulamanın oturumlar arası dosyaları yeniden açmasına olanak tanır. Kullanıcı showOpenFilePicker aracılığıyla izin verdikten sonra FileSystemFileHandle'ı IndexedDB'de kalıcı hale getirebilir ve daha sonra her dosya için yeniden istem vermeksizin erişimi yeniden almak için handle.requestPermission() çağrısı yapabilirsiniz.

Geçici Alan için OPFS

Kaynak Özel Dosya Sistemi, bir dosya sistemi gibi davranan ancak kullanıcıya görünmeyen, kaynak başına korumalı bir depolamadır:

const root = await navigator.storage.getDirectory();
const fh = await root.getFileHandle('scratch.bin', { create: true });
const access = await fh.createSyncAccessHandle(); // yalnızca worker'lar
access.write(buffer, { at: offset });
access.flush();
access.close();

createSyncAccessHandle yalnızca Web Worker'ların (Service Worker'lar dahil) içinde kullanılabilir. Zaman uyumludur ve son derece hızlıdır — karşılaştırmalar sıralı yazmalar için IndexedDB'den 3-10 kat daha iyi sonuç gösterir. Yüklemeden önce birkaç yüz megabaytlık şifreleme çıktısını arabelleğe almak veya kullanıcının İndirmeler klasörünü kirletmeden şifresi çözülmüş çalışma kopyasını önbelleğe almak için kullanın.

Safari 17, eşzamanlı erişim tanıtıcılarıyla birlikte OPFS'i gönderdi; Firefox 111 ardından geldi. Üç büyük tarayıcının tamamı artık bunu destekliyor ve bu durum üretim kodu için uygun hale getiriyor.

Depolama Kotaları ve Onlarla Başa Çıkma

Her API aynı kaynak kota havuzunu paylaşır. Yaklaşık üst sınırlar:

  • Masaüstü Chrome: Boş diskin %60'ı
  • Masaüstü Firefox: Boş diskin %50'si, varsayılan olarak kaynak başına 2 GB ile sınırlı
  • Masaüstü Safari: 1 GB uyarısı, kullanıcı onayıyla diskin ~%20'sine büyür
  • iOS Safari: Kaynak başına 1 GB, kullanılmadığında agresif 7 günlük tahliye
  • Android Chrome: Boş diskin %10'u, baskı altında tahliye

Çalışma zamanında kotayı kontrol edin:

const { quota, usage } = await navigator.storage.estimate();
console.log(`Using ${(usage/1e9).toFixed(2)} GB of ${(quota/1e9).toFixed(2)} GB`);

Kritik depolar için kalıcılık isteyin:

const persisted = await navigator.storage.persist();

Tarayıcı kalıcı depolamayı verdiyse true döner; bu, baskı altında tahliye etmeyeceği anlamına gelir. Chrome bunu kullanıcının önemli ölçüde etkileşime girdiği sitelere otomatik olarak verir; Firefox kullanıcıya sorar.

Uygulama Kabuğu ve Çevrimdışı için Cache API

Cache API, Request + Response çiftlerini saklar ve Service Worker'ların içinde doğru seçimdir:

const cache = await caches.open('shell-v7');
await cache.addAll([
  '/', '/app.js', '/app.css', '/icons/192.png'
]);

Kesişimde alın:

self.addEventListener('fetch', (e) => {
  e.respondWith(caches.match(e.request).then(r => r ?? fetch(e.request)));
});

Şifreli dosya baytlarını Cache API'ye koymayın. 2 GB'lık bir yanıt nesnesi iOS Safari'nin kotasını tek seferde aşar ve sonrasında aralıklı olarak alınamaz. Baytlar OPFS'e veya Dosya Sistemi Erişimi aracılığıyla doğrudan diske aittir.

Tahliye ve Veri Kaybını Zarif Biçimde Yönetme

Kalıcı olmayan depolama tahliye edilir — bunu planlamalısınız. iOS Safari, kotadan bağımsız olarak 7 günlük hareketsizliğin ardından tahliye eder. Chrome yalnızca disk gerçekten baskı altındayken tahliye eder. Firefox, kota havuzu dolduğunda en son kullanılan kaynakları tahliye eder.

İki savunma deseni:

  • Yeniden oluşturamadığınız herhangi bir durumu (yükleme oturumu kimliklerini, kısmi parça ofsetlerini) yeniden yükleme dostu bir biçimde yazın; böylece taze bir sayfa yüklemesi sunucudan yeniden alabilir ve devam edebilir.
  • Uzun süreli durum için navigator.storage.persist() isteyin ve tarayıcı kullanıcıya sorduğunda onaylamaları için bir kullanıcı arayüzü sunun.

Kaybetmeyi göze alamadığınız her şey için sunucuyu gerçeğin kaynağı olarak tutun. Tarayıcı depolamasına bir gecede yok olabilecek hızlı bir önbellek gözüyle bakın.

Tarayıcı Desteği Mayınları

Üç tuzak tekrar tekrar karşımıza çıkar:

  1. indexedDB.databases() numaralandırması Firefox'ta desteklenmez ("kapanışta çerezleri sil" seçeneğini etkinleştiren kullanıcılar olay tetiklemeden tüm IndexedDB içeriğini kaybeder).
  2. FileSystemFileHandle.queryPermission(), yeniden yüklemelerin ardından farklı davranır — verilmiş olsa bile bazen 'prompt' döndürür. Her zaman savunma amaçlı requestPermission() çağrısı yapın.
  3. Özel/gizli mod, üç API'ye de ayrı, daha küçük, yalnızca oturum geçerli kota verir. Normal taramada çalışan kod, özel pencerelerde hemen QuotaExceededError verebilir.

HexaTransfer oturum durumu için IndexedDB kullanır, akış şifreleme sırasında şifreli metin arabelleği için OPFS kullanır ve desteklenen tarayıcılarda 10 GB şifresi çözülmüş indirmeler için Dosya Sistemi Erişim API'sini kullanır. hexatransfer.com'da deneyin — ücretsiz, hesap gerekmez, maksimum 10 GB.

Uygulamanız için Bir Yığın Seçimi

Çoğu transfer uygulaması için doğru kombinasyon şudur: meta veriler için IndexedDB sarmalayıcısı olarak idb, şifrele/şifre çöz geçici alanı için OPFS eşzamanlı erişim tanıtıcıları, Service Worker içinde uygulama kabuğu için Cache API, StreamSaver geri dönüşüyle birlikte son indirmeler için Dosya Sistemi Erişim API'si ve katılım sırasında yapılan bir navigator.storage.persist() çağrısı. Bu, bugün sevk edilen tüm tarayıcıları kapsar, mobilde kotaların altında kalır ve bir şey tahliye edildiğinde zarif biçimde kurtarır. Her API etrafında küçük bağdaştırıcılar oluşturun; böylece OPFS yeni bir yöntem eklediğinde veya Safari kotasını artırdığında tek bir dosyayı değiştirip gönderirsiniz.

Uçtan uca şifreleme ile büyük dosyaları güvenle gönderin

Uçtan uca şifreleme ile 10 GB'a kadar dosya ücretsiz aktarın. Hesap gerekmez. Dosyalarınız yüklenmeden önce tarayıcınızda şifrelenir — başka kimse okuyamaz.

Dosya gönder