Episode ini membahas transfer file lewat WebSocket: transfer ber-chunk dengan binary, pemantauan progres, kemampuan pause dan resume, serta optimasi ukuran chunk, kompresi, dan bandwidth.

File besar lewat HTTP biasa artinya mengunggah sekali lalu menunggu. Dengan WebSocket, transfer bisa berjalan lebih hidup: progres terlihat per persen, bisa dijeda dan dilanjutkan, bahkan beberapa file dikirim paralel. Namun file raksasa juga bisa meledakkan memori jika ditangani naif.
Episode 24 membahas file transfer over WebSocket: memecah file menjadi chunk, mengirimnya sebagai binary, memantau progres, dan menyusunnya kembali di server. Kalian akan membangun mekanisme transfer yang aman untuk file ratusan megabyte.
Satu koneksi WebSocket bisa menangani frame raksasa, tapi jangan: memori server akan meledak, dan satu kegagalan memaksa mengulang semuanya. Pecah file menjadi chunk kecil:
metadata -> chunk 1 -> chunk 2 -> ... -> selesaiChunk berukuran 16-64 KB adalah titik manis: cukup besar untuk efisien, cukup kecil untuk perpesan tunggal yang bisa ditangani event loop dengan ringan.
Selalu kirim metadata di awal agar server tahu apa yang datang.
const metadata = {
type: "file:start",
nama: "laporan.pdf",
ukuran: 5242880,
totalChunk: 320,
chunkSize: 16384,
id: "transfer_7f9a",
};metadata membawa nama, ukuran, dan jumlah chunk. Server memvalidasi ukuran terhadap kebijakan (misalnya maksimal 100 MB) sebelum menyetujui transfer dengan event file:start-ok.
Di sisi klien, file dibaca lalu dipecah dengan slice.
const file = input.files[0];
const CHUNK = 16384;
for (let mulai = 0; mulai < file.size; mulai += CHUNK) {
const chunk = file.slice(mulai, mulai + CHUNK);
const buffer = await chunk.arrayBuffer();
ws.send(buffer);
}file.slice(mulai, mulai + CHUNK) mengambil sebagian file tanpa memuat seluruhnya ke memori, dan chunk.arrayBuffer() mengubahnya menjadi data yang bisa dikirim lewat ws.send(buffer).
Server mengumpulkan chunk berdasarkan identitas transfer.
const transfers = new Map();
ws.on("message", (data) => {
if (data.toString().startsWith("{")) {
const meta = JSON.parse(data.toString());
transfers.set(meta.id, {
nama: meta.nama,
chunks: [],
total: meta.totalChunk,
});
return;
}
const t = transfers.get(ws.transferId);
t.chunks.push(Buffer.from(data));
ws.emitProgres();
});Server membedakan pesan JSON (kontrol) dan buffer (chunk) dari data.toString().startsWith("{"). Chunk dikumpulkan dalam urutan kedatangan, lalu di-join menjadi satu Buffer saat jumlahnya lengkap.
Progres dihitung dari chunk yang sudah terkirim.
let terkirim = 0;
const total = 320;
for (let i = 0; i < total; i++) {
await kirimChunk(i);
terkirim += 1;
ws.emit("file:progress", {
persen: Math.round((terkirim / total) * 100),
});
}Math.round((terkirim / total) * 100) mengubah chunk yang terkirim menjadi persen. Klien menampilkan bar progres dan mengupdate-nya setiap chunk — detail kecil yang membuat transfer terasa responsif.
Dengan chunk bernomor, resume menjadi mudah: klien menanyakan chunk terakhir yang diterima server.
ws.on("file:resume", (id) => {
const t = transfers.get(id);
ws.send(JSON.stringify({
type: "file:status",
id,
chunkBerikut: t.chunks.length,
}));
});chunkBerikut: t.chunks.length memberi tahu klien titik melanjutkan. Klien yang terputus cukup meminta status lalu mengirim chunk mulai dari nomor itu — tidak perlu mengulang dari awal.
Ukuran chunk memengaruhi throughput dan latensi:
Untuk file teks dan JSON, kompresi mengurangi ukuran drastis. Untuk media yang sudah terkompresi seperti gambar JPEG atau video, kompresi tambahan hanya membuang CPU.
Beberapa file bisa dikirim bersamaan lewat satu koneksi dengan identitas transfer berbeda. Server memproses transfer paralel dengan batas jumlah agar tidak saling berebut bandwidth. Prioritaskan transfer kecil lebih dulu agar tidak menunggu file besar.
Chat yang mengirim gambar memakai pola ini: thumbnail kecil dikirim dulu untuk tampil seketika, file asli menyusul di belakang. Pengguna melihat pratinjau cepat, lalu gambar penuh muncul saat selesai.
Editor kolaboratif memakai transfer WebSocket untuk melampirkan aset: drag-and-drop gambar masuk ke dokumen langsung lewat WebSocket, muncul sebagai placeholder, lalu selesai sebagai gambar utuh.
Episode 24 memberi kalian mekanisme transfer file yang aman dan hidup: chunk yang melindungi memori, binary yang efisien, progres yang memotivasi, dan resume yang menyelamatkan saat koneksi terputus.
Inti yang harus dibawa pulang:
Di episode 25 berikutnya kita membahas video/audio signaling dengan WebRTC: peran WebSocket sebagai signaling channel, pertukaran SDP dan ICE candidate, serta konfigurasi STUN dan TURN.