Lompat ke konten
20 menit bacamateri 85 dari 96

Unggah langsung ke penyimpanan

Kenapa byte besar sebaiknya nggak lewat server aplikasi, dan gimana signed URL, multipart, checksum, serta pembersihan menjaga unggahan tetap benar.

Ditinjau 26 Oktober 2026

Pertanyaan

Gimana klien ngunggah berkas besar ke penyimpanan tanpa bikin server aplikasi jadi jalur bandwidth, dan gimana kita tahu hasilnya utuh?

Setelah baca ini, kamu bisa ngerancang alur unggah dengan signed URL dan multipart, nentuin di mana checksum dan kedaluwarsa dipasang, dan nyebut cara bersihin unggahan yang ditinggal separuh jalan.

Prasyarat dan contoh

Kamu sudah kenal kontrak API dan idempotensi (M03), cache (M06), durabilitas penyimpanan (M09), dan antrean job (M10).

Aplikasi dokumen nerima PDF rata-rata 40 MB. Awalnya klien kirim berkas ke endpoint aplikasi, lalu aplikasi nerusin ke object storage. Dengan 200 unggahan bersamaan, aplikasi harus megang 200 x 40 MB = 8 GB data yang lagi jalan, plus koneksi yang kebuka berpuluh detik di jaringan seluler. Worker aplikasi habis oleh koneksi lambat, padahal CPU hampir nganggur. Endpoint GET /dokumen yang ringan ikut lambat.

Masalahnya bukan storage-nya. Masalahnya byte besar lewat komponen yang cuma perlu memutuskan siapa boleh ngunggah.

Mekanisme

Pisahkan jalur kontrol dari jalur data. Aplikasi cuma ngurus izin dan metadata. Byte-nya langsung dari klien ke storage:

1. klien → aplikasi:  "mau unggah laporan.pdf, 40 MB, sha256=..."
2. aplikasi:          cek izin dan kuota, catat unggahan status "menunggu"
3. aplikasi → klien:  signed URL (berlaku 15 menit, key tertentu)
4. klien → storage:   PUT byte langsung
5. klien → aplikasi:  "selesai"
6. aplikasi → storage: cek ukuran dan checksum, ubah status jadi "siap"

Signed URL. URL ini membawa tanda tangan yang mengikat metode, key objek, waktu kedaluwarsa, dan biasanya header tertentu seperti Content-Type atau Content-Length. Storage bisa memverifikasinya tanpa nanya aplikasi. Key sebaiknya dibuat server (misalnya unggahan/<id-unggahan>/asli), bukan nama berkas dari klien, supaya klien nggak bisa menimpa objek orang lain atau nulis ke path yang nggak diizinkan. Umur URL pendek: cukup buat satu percobaan, bukan buat disimpan.

Multipart. Berkas 2 GB dalam satu PUT gagal total kalau koneksi putus di 95%. Dengan multipart, berkas dipecah jadi bagian. Contoh di S3: tiap bagian minimal 5 MiB (kecuali yang terakhir), maksimal 10.000 bagian per unggahan. Klien meminta ID unggahan, mengirim bagian secara paralel (tiap bagian punya signed URL sendiri), lalu mengirim daftar nomor bagian beserta ETag-nya untuk menyelesaikan. Bagian yang gagal diulang sendiri, bukan seluruh berkas. Ukuran bagian itu kompromi: 8 MiB berarti berkas 2 GB jadi 256 bagian, request lebih banyak tapi ulang lebih murah.

Checksum. Koneksi yang sukses bukan bukti byte-nya utuh. Klien menghitung SHA-256 (atau CRC32C per bagian kalau storage mendukung) dan mengirimnya di awal. Storage atau aplikasi membandingkan setelah selesai. Kalau beda, unggahan ditandai gagal dan nggak pernah masuk status "siap". Perhatikan: ETag multipart di banyak storage bukan hash isi seluruh berkas, jadi jangan dipakai sebagai checksum isi.

Status dan kedaluwarsa. Catatan unggahan punya status menunggu → selesai → siap atau gagal/kedaluwarsa. Objek baru boleh dirujuk dokumen lain hanya setelah siap. Unggahan yang melewati batas waktu (misalnya 24 jam) otomatis jadi kedaluwarsa.

Pembersihan. Bagian multipart yang nggak pernah diselesaikan tetap disimpan dan ditagih. Pasang aturan lifecycle buat membatalkan multipart yang menggantung lebih dari 1 sampai 7 hari, plus job pembersih yang menghapus objek berstatus menunggu yang sudah kedaluwarsa.

Saat rancangan ini gagal

  • Klien menimpa objek yang bukan miliknya. Terjadi kalau key diambil dari input klien atau signed URL dibuat untuk prefix yang terlalu luas. Buat key di server dan tanda tangani satu key saja.
  • Aplikasi percaya ukuran dari klien. Klien bilang 40 MB, lalu kirim 40 GB. Pasang batas Content-Length di signed URL atau kebijakan upload, dan cek ukuran sebenarnya di storage.
  • Unggahan setengah jadi menumpuk. 5.000 pengguna per hari meninggalkan 100 MB bagian multipart: setelah sebulan 15 TB tagihan buat data yang nggak bisa dipakai.
  • Selesai tanpa verifikasi. Klien memanggil "selesai" dua kali, atau memanggilnya padahal bagian ke-37 belum sampai. Endpoint "selesai" harus idempoten dan memeriksa kondisi nyata.
  • Signed URL bocor. Siapa pun yang punya URL bisa memakainya sampai kedaluwarsa. Umur pendek dan batasan key mengecilkan kerusakannya, tapi nggak menghilangkannya.

Latihan

Aplikasi klinik menerima hasil pindai 500 MB (rata-rata), 300 unggahan per jam di jam sibuk, dan klien sering memakai Wi-Fi yang putus-nyambung. Sekarang unggahan lewat endpoint aplikasi dan sering timeout di menit ke-4. Rancang alur barunya: sebutkan cara memecah berkas, apa yang dicek sebelum status jadi siap, dan apa yang dibersihkan.

Lihat pembahasan

Alur: aplikasi membuat catatan unggahan menunggu (dengan pemilik, ukuran yang diklaim, SHA-256), memulai multipart di storage dengan key buatan server, lalu memberi signed URL per bagian berumur 15 menit.

Pemecahan: bagian 16 MiB, jadi 500 MB menjadi sekitar 32 bagian. Cukup besar supaya jumlah request kecil, cukup kecil supaya Wi-Fi putus hanya mengulang 16 MiB, bukan 500 MB. Klien mengirim 3 sampai 4 bagian paralel dan meminta URL baru kalau URL bagian kedaluwarsa.

Sebelum siap: server memanggil complete, lalu mengecek ukuran akhir sama dengan klaim dan checksum sama dengan yang dikirim di awal. Endpoint complete idempoten, jadi retry klien aman. Kalau ukuran atau hash beda, status gagal dan objek dihapus.

Pembersihan: aturan lifecycle membatalkan multipart yang menggantung lebih dari 2 hari, dan job per jam menandai unggahan menunggu yang lewat 24 jam sebagai kedaluwarsa lalu membatalkan multipart-nya. Beban: 300 unggahan per jam x 500 MB = 150 GB per jam lewat storage, bukan lewat aplikasi.

Jawaban yang bagus menyebut ukuran bagian dengan alasan, verifikasi sebelum publikasi, dan pembersihan yang terjadwal.

Terkait

  • Berikutnya di modul ini: Sajikan gambar melalui CDN (M15.02) membahas gimana berkas yang sudah siap disajikan.
  • Proses video secara asinkron (M15.03) memakai pola status dan job yang sama setelah unggahan selesai.
  • Idempotensi di M03 dan antrean job di M10 membahas dasar endpoint complete yang aman diulang.
  • Lab L15 dan proyek B11 belum tersedia.

Catatan

  • Asumsi: object storage yang mendukung signed URL dan multipart (batas angka di atas contoh S3, cek dokumentasi penyedia yang kamu pakai).
  • Yang nggak dibahas: unggah resumable berbasis protokol khusus seperti tus, enkripsi sisi klien, dan pemindaian malware.
  • Pemindaian virus atau validasi isi biasanya jadi langkah tambahan antara selesai dan siap.
  • Terakhir ditinjau: 26 Oktober 2026.

Isi · System Design