Topik temu duga representatif

Temu duga frontend: Bagaimanakah anda memproses fail besar secara selamat dengan Compression Streams?

FrontendSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Pelayar mesti memampatkan (gzip) muat naik besar dan menyahmampat muat turun dengan penggunaan memori yang rendah, sokongan pembatalan dan perlindungan daripada input berniat jahat. Reka bentuk saluran paip strim dan terangkan format, tekanan balik, ralat dan sempadan keselamatan.

Gesaan dan konteks

Pelayar mesti memampatkan (gzip) muat naik besar dan menyahmampat muat turun dengan penggunaan memori yang rendah, sokongan pembatalan dan perlindungan daripada input berniat jahat. Reka bentuk saluran paip strim dan terangkan format, tekanan balik, ralat dan sempadan keselamatan.

Compression Streams API menyediakan CompressionStream dan DecompressionStream untuk ketulan binari dalam saluran paip Web Streams. Piawaian ini mentakrifkan brotli, deflate, deflate-raw dan gzip; ia menyediakan transformasi, bukan had saiz, pengesahan (authentication) atau semakan integriti perniagaan.

Perkara yang diuji oleh penemu duga

Merangkumi komposisi Readable/Writable/TransformStream, tekanan balik (backpressure) dan barisan gilir, pam (flush), sempadan format, ralat penyahmampatan, penyebaran pembatalan, bajet memori, bom penyahmampatan dan saluran sisi panjang (length side channels), peningkatan progresif, serta rundingan pelayan.

Rangka kerja jawapan 30 saat

“Saya akan menyambungkan strim Blob atau badan respons kepada CompressionStream dengan pipeThrough supaya tekanan balik dikekalkan, dan menyebarkan pembatalan menggunakan AbortSignal. Semasa memuat turun, hadkan saiz mampatan, bait yang dinyahmampat dan masa pemprosesan sebelum menyalurkan DecompressionStream kepada penghurai (parser); batalkan jika terdapat ralat format atau integriti. Jika pelayar tidak mempunyai keupayaan ini, gunakan mampatan pelayan sebagai sandaran. API ini bukan pengimbas keselamatan atau pengesah integriti.”

Analisis mendalam langkah demi langkah

Langkah 1: Pilih strim input dan output

Muat naik boleh bermula daripada Blob.stream() dan muat turun daripada Response.body. Suatu CompressionStream menghasilkan ReadableStream untuk badan fetch, penerima fail (file sink) atau penghurai; jangan muatkan keseluruhan fail ke dalam ArrayBuffer terlebih dahulu.

Langkah 2: Sambungkan transformasi

Saluran paip muat naik yang minimum ialah:

javascript
async function uploadGzip(blob, signal) {
  const compressed = blob.stream().pipeThrough(
    new CompressionStream("gzip"),
    { signal },
  );
  return fetch("/upload", {
    method: "POST",
    body: compressed,
    signal,
    headers: { "Content-Encoding": "gzip" },
  });
}

Protokol sebenar mesti mentakrifkan panjang permintaan, semantik percubaan semula (retry) dan sama ada pelayan menerima badan permintaan penstriman.

Langkah 3: Fahami tekanan balik (backpressure) dan pam (flush)

Streams API melaraskan bacaan huluan (upstream) berdasarkan barisan gilir dan kelajuan penulisan hiliran (downstream). Jangan tambahkan setiap ketulan ke dalam tatasusunan tanpa had; penerima yang perlahan sepatutnya menjeda saluran paip secara semula jadi. Menutup bahagian boleh tulis (writable) mesti mengepam (flush) blok mampatan akhir dan checksum.

Langkah 4: Rundingkan format

Pembina menerima rentetan format yang disokong dan melontarkan ralat bagi format yang tidak disokong. Klien dan pelayan mesti bersetuju dengan Content-Encoding atau medan perniagaan. deflate, deflate-raw dan gzip mempunyai pembungkus (wrappers) yang berbeza; jangan hantar Brotli tanpa rundingan.

Langkah 5: Jadikan penyahmampatan berbatas

Input termampat boleh berkembang menjadi output yang amat besar. Kira bait output, entri fail, masa pemprosesan dan tugas serentak; batalkan atau hentikan serta-merta sebaik sahaja bajet dilampaui. Kandungan yang dinyahmampat masih memerlukan semakan MIME, laluan dan keselamatan kandungan. Transformasi yang berjaya bukanlah jaminan kepercayaan.

Langkah 6: Sebarkan ralat dan pembatalan

Kegagalan format atau checksum meletakkan transformasi ke dalam keadaan ralat. Tangkap ralat daripada pipeTo, fetch dan pembaca, serta sebarkan pembatalan pengguna kepada permintaan, pembaca, penulis dan transformasi. Lepaskan Blob sementara, kunci (locks) dan status kemajuan UI supaya tiada bacaan yang kekal tergantung.

Langkah 7: Lindungi privasi dan integriti

Panjang termampat boleh mendedahkan hubungan antara rahsia dan teks yang dikawal penyerang. Jangan letakkan kedua-duanya dalam satu konteks mampatan yang sama. Gunakan tandatangan atau cincangan (hash) bebas untuk fail penting; mampatan mengekod bait tetapi tidak mengesahkan punca atau menghalang pengubahan data.

Langkah 8: Sediakan keserasian dan sandaran (fallback)

Periksa pembina dan format semasa permulaan, dan jalankan tugas berat di dalam Worker untuk melindungi benang utama (main thread). Jika tidak disokong, serahkan kepada mampatan pelayan atau muat naik tanpa mampatan dengan semantik pembatalan, saiz dan ralat yang sama; jangan hanya mengesahkan pada pelayar moden.

Pertukaran kompromi (trade-offs) dan sempadan

CPU klien berbanding penjimatan rangkaian

Mampatan menjimatkan bait tetapi menggunakan CPU, bateri dan masa. Pada peranti mudah alih, pilih berdasarkan jenis fail, kualiti rangkaian dan bateri; format yang sudah dimampatkan biasanya tidak perlu dimampatkan semula.

Penstriman berbanding kesederhanaan percubaan semula

Penstriman memastikan penggunaan memori kekal rendah tetapi memerlukan pelayan yang peka ketulan dan percubaan semula yang idempoten. Bagi muat naik yang boleh disambung semula (resumable), ikat ketulan termampat pada protokol multipart; jangan cuba semula ReadableStream yang telah digunakan seolah-olah ia boleh dimainkan semula (replayable).

Penyahmampatan pelayar berbanding pelayan

Penyahmampatan pelayar menjimatkan CPU pelayan tetapi memindahkan bajet sumber dan keselamatan ke peranti. Untuk data yang sensitif atau berkadar pengembangan tinggi, nyahmampat pada pelayan dan kembalikan hasil yang terhad sementara klien menggunakan status dan ketulan.

Latih tubi kegagalan dan pelan evolusi

Penerima (sink) menjadi perlahan

Kawal kelajuan muat naik (throttle) dan periksa keluk barisan gilir serta memori. Sahkan bahawa ketulan tidak disimpan semuanya di dalam memori; jika barisan gilir masih berkembang, kurangkan keserentakan dan biarkan saluran paip dijeda.

Strim gzip terputus (truncated)

Putuskan input termampat dan sahkan kegagalan semasa mengepam (flush) atau pengesahan checksum, keadaan UI yang boleh dicuba semula, serta pelepasan pembaca, permintaan dan objek sementara.

Output melebihi bajetnya

Gunakan sampel pengembangan tinggi dan sahkan bahawa mencapai had bait akan membatalkan proses serta-merta dan bukannya merealisasikan atau mengekalkan keseluruhan output.

Kesilapan lazim dan tindakan susulan

Kesilapan 1: Menganggap API menghalang bom penyahmampatan

Tindakan susulan: Apakah yang tertinggal? Bajet bait, masa, entri dan keserentakan pada peringkat aplikasi; API ini hanya melaksanakan penukaran format.

Kesilapan 2: Menganggap deflate sebagai gzip

Tindakan susulan: Mengapa tidak? Pembungkusnya berbeza, jadi rundingan protokol dan format yang sepadan diperlukan.

Kesilapan 3: Mencuba semula strim yang telah digunakan

Tindakan susulan: Apakah langkah yang betul? Bina semula saluran paip daripada sumber ketulan atau Blob yang boleh dimainkan semula dan selaraskan pengecam muat naik yang idempoten dengan pelayan.

Tindakan susulan lanjutan dan model jawapan

Mengapakah flush (pengepaman) penting?

Transformasi mesti mengeluarkan data mampatan penamat (trailer) dan checksum apabila input tamat. Tanpa menutup bahagian boleh tulis, pengguna boleh menerima strim yang tidak lengkap.

Bagaimanakah anda mengurangkan risiko saluran sisi panjang (length side-channel)?

Asingkan rahsia daripada teks yang dikawal penyerang, elakkan konteks mampatan yang dikongsi, dan gunakan pelapik (padding) protokol atau reka bentuk yang tidak mendedahkan hubungan tersebut.

Bilakah mampatan patut kekal pada pelayan?

Gunakan pemprosesan sebelah pelayan untuk pelayar lama, peranti bateri rendah, fail yang sangat besar atau data sensitif. Tetap hadkan output yang dinyahmampat dan paparkan kemajuan yang boleh diperhatikan kepada klien.

Sumber awam

Soalan berkaitan