tutorial

29 Studi Kasus: Streaming Upload File

Streaming File Upload dengan Go dan gRPC

Mengunggah file besar adalah tantangan klasik dalam pengembangan backend, terlebih ketika sistem harus mampu menangani ratusan MB atau bahkan GB dalam satu sesi. Bila dilakukan secara konvensional (buffer all then store), risiko overload memory dan kegagalan sangat tinggi. Di sinilah pentingnya pendekatan streaming upload.

Artikel ini akan membahas cara mengimplementasikan streaming file upload menggunakan Go dan gRPC streaming. Kita akan menyimulasikan API upload file besar dari klien ke server, yang ditangani secara chunked.


Kenapa Memilih gRPC Streaming?

Dengan gRPC streaming, kita bisa:

  • Mengirim data bertahap dalam bentuk chunk.
  • Menghindari memory overuse.
  • Memberikan feedback progres upload.
  • Mengelola upload file besar secara efisien dan scalable.

Arsitektur dan Alur Streaming Upload

sequenceDiagram
    participant Client
    participant gRPCServer
    participant Disk

    Client->>gRPCServer: stream Upload(chunk)
    loop Selama upload
        gRPCServer->>Disk: write(chunk)
    end
    gRPCServer-->>Client: UploadResponse(status)

1. Definisi Protobuf

syntax = "proto3";

package upload;

service FileService {
  rpc Upload(stream UploadRequest) returns (UploadResponse);
}

message UploadRequest {
  bytes chunk = 1;
  string filename = 2; // hanya dikirim di awal chunk
}

message UploadResponse {
  string message = 1;
  bool success = 2;
}

2. Implementasi Server gRPC di Go

a. Setup Server

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"os"
	"google.golang.org/grpc"
	"net"
	pb "your_project/proto/upload"
)

type server struct {
	pb.UnimplementedFileServiceServer
}

func (s *server) Upload(stream pb.FileService_UploadServer) error {
	var file *os.File
	firstChunk := true

	for {
		req, err := stream.Recv()
		if err == io.EOF {
			return stream.SendAndClose(&pb.UploadResponse{
				Message: "Upload selesai",
				Success: true,
			})
		}
		if err != nil {
			return err
		}

		if firstChunk {
			file, err = os.Create("uploads/" + req.Filename)
			if err != nil {
				return err
			}
			defer file.Close()
			firstChunk = false
		}

		_, err = file.Write(req.Chunk)
		if err != nil {
			return err
		}
	}
}

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("gagal listen: %v", err)
	}

	s := grpc.NewServer()
	pb.RegisterFileServiceServer(s, &server{})
	log.Println("Server gRPC berjalan di port 50051")
	s.Serve(lis)
}

3. Simulasi Klien Upload Streaming

conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
defer conn.Close()

client := pb.NewFileServiceClient(conn)
stream, _ := client.Upload(context.Background())

f, _ := os.Open("large.pdf")
buf := make([]byte, 1024*32) // 32 KB per chunk

stream.Send(&pb.UploadRequest{Filename: "large.pdf"})

for {
	n, err := f.Read(buf)
	if err == io.EOF {
		break
	}
	stream.Send(&pb.UploadRequest{Chunk: buf[:n]})
}

res, _ := stream.CloseAndRecv()
fmt.Println("Respon server:", res.Message)

4. Perbandingan: Buffer vs Streaming

ParameterBuffer UploadgRPC Streaming
Memory UsageTinggi (file tersimpan di memori)Stabil (per chunk)
Time to WriteSetelah semua data diterimaSegera selama upload
SkalabilitasBurukBaik (support paralel)
KompleksitasRendahMenengah

5. Tips Produksi

  • ✅ Gunakan validasi ukuran file pada klien dan server.
  • ✅ Batasi ukuran chunk dan maksimum file (gunakan metadata).
  • ✅ Tambahkan TLS + metadata untuk autentikasi.
  • ✅ Stream langsung ke cloud storage (misalnya Google Cloud Storage atau S3) untuk efisiensi.
  • ✅ Logging dan tracing sangat membantu debugging.

Kesimpulan

Streaming upload file dengan gRPC di Go memberikan efisiensi tinggi dan kontrol granular terhadap aliran data. Pendekatan ini sangat cocok untuk aplikasi yang melayani file besar, pengguna banyak, atau butuh performa tinggi.

gRPC streaming adalah alat yang powerful jika digunakan dengan benar. Jika arsitektur aplikasi Anda melibatkan upload file besar — sudah waktunya beralih ke pendekatan ini.


Ingin saya bantu setup modul upload file stream dengan validasi metadata dan monitoring Prometheus? Tulis saja! 🚀

comments powered by Disqus