Belajar WebSocket - File Transfer over WebSocket
Episode 24 of 34

Belajar WebSocket - File Transfer over WebSocket

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.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

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.

Pola Transfer Ber-Chunk

Kenapa Harus di-Chunk

Satu koneksi WebSocket bisa menangani frame raksasa, tapi jangan: memori server akan meledak, dan satu kegagalan memaksa mengulang semuanya. Pecah file menjadi chunk kecil:

Alur transfer file
metadata -> chunk 1 -> chunk 2 -> ... -> selesai

Chunk berukuran 16-64 KB adalah titik manis: cukup besar untuk efisien, cukup kecil untuk perpesan tunggal yang bisa ditangani event loop dengan ringan.

Metadata dan Kontrol

Selalu kirim metadata di awal agar server tahu apa yang datang.

JSMetadata transfer file
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.

Implementasi Transfer

Mengirim Chunk dari Browser

Di sisi klien, file dibaca lalu dipecah dengan slice.

JSKirim file ber-chunk di browser
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).

Menyusun Kembali di Server

Server mengumpulkan chunk berdasarkan identitas transfer.

JSServer menyusun file
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 dan Resume

Memantau Progres

Progres dihitung dari chunk yang sudah terkirim.

JSHitung dan kirim progres
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.

Pause dan Resume

Dengan chunk bernomor, resume menjadi mudah: klien menanyakan chunk terakhir yang diterima server.

JSResume dari chunk terakhir
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.

Optimasi Transfer

Ukuran Chunk dan Kompresi

Ukuran chunk memengaruhi throughput dan latensi:

  • 16 KB: latensi terendah, overhead header lebih banyak.
  • 64 KB: keseimbangan baik untuk kebanyakan jaringan.
  • 1 MB: throughput maksimal, tapi satu kegagalan mengulang banyak data.

Untuk file teks dan JSON, kompresi mengurangi ukuran drastis. Untuk media yang sudah terkompresi seperti gambar JPEG atau video, kompresi tambahan hanya membuang CPU.

Transfer Paralel

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.

Use Case

Gambar dalam Chat

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.

Kolaborasi Dokumen

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.

Penutup

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:

  • Pecah file besar menjadi chunk agar tidak meledakkan memori.
  • Kirim metadata lalu identifikasi chunk dengan ID transfer.
  • Browser membaca file sebagian dengan slice tanpa memuat penuh.
  • Progres dihitung dari chunk yang terkirim, bukan ukuran byte.
  • Nomor chunk memungkinkan pause dan resume dari titik putus.
  • Kompresi membantu file teks, sia-sia untuk media terkompresi.

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.

Belajar WebSocket - File Transfer over WebSocket | Belajar WebSocket