Skip to content

File Uploads Guide ​

Panduan upload file dan gambar di aplikasi.

📁 Dua Jenis Upload ​

TipeAPIUse CaseConvert
Image/api/upload/imageAvatar, photosWebP
File/api/upload/presignPDF, ZIP, DOC-

🖼️ Image Upload (Avatar) ​

Cara Kerja ​

  1. User pilih file (JPG, PNG, GIF, WebP)
  2. Server convert ke WebP
  3. Resize jika avatar (256x256)
  4. Upload ke R2
  5. Return public URL

Upload Avatar ​

Di Profile page:

  1. Klik icon kamera di avatar
  2. Pilih gambar dari komputer
  3. Preview muncul
  4. Klik "Upload Avatar"
  5. Done! ✅

Via API ​

typescript
const formData = new FormData();
formData.append('file', imageFile);
formData.append('type', 'avatar'); // atau 'general'

const res = await fetch('/api/upload/image', {
  method: 'POST',
  body: formData
});

const { url, size } = await res.json();
// url: https://pub-xxx.r2.dev/avatars/user-id/timestamp.webp

Image Processing ​

Auto-convert ke WebP:

  • Ukuran lebih kecil (30-50%)
  • Kualitas tetap baik
  • Browser support modern

Avatar (type='avatar'):

  • Square crop (center)
  • Resize ke 256x256
  • Quality: 90%

General Image (type='general'):

  • Max 1920x1920
  • Quality: 85%
  • Maintain aspect ratio

Validasi ​

  • ✅ Max 5MB
  • ✅ Format: JPG, PNG, GIF, WebP
  • ❌ Tidak accept: SVG, BMP, TIFF

📄 File Upload (PDF, ZIP, etc) ​

Cara Kerja (Presigned URL) ​

  1. Minta presigned URL dari server
  2. Upload langsung ke R2 dari browser
  3. Server receive confirmation

Via API ​

Step 1: Get Presigned URL

typescript
const res = await fetch('/api/upload/presign', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    filename: 'document.pdf',
    contentType: 'application/pdf',
    prefix: 'documents' // folder di R2
  })
});

const { uploadUrl, publicUrl } = await res.json();

Step 2: Upload ke R2

typescript
await fetch(uploadUrl, {
  method: 'PUT',
  body: file,
  headers: { 'Content-Type': 'application/pdf' }
});
// File sekarang di R2!

Allowed File Types ​

TypeMIME Type
PDFapplication/pdf
ZIPapplication/zip
JSONapplication/json
TXTtext/plain
CSVtext/csv
Excelapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Wordapplication/vnd.openxmlformats-officedocument.wordprocessingml.document

🗂️ Struktur Folder di R2 ​

bucket/
├── avatars/
│   └── {user-id}/
│       └── timestamp.webp
├── uploads/
│   └── {user-id}/
│       └── document.pdf
└── images/
    └── {user-id}/
        └── photo.webp

🔒 Security ​

Access Control ​

  • Avatar: Public URL (bisa diakses semua)
  • File upload: Bisa di-restrict dengan presigned URL
  • Delete: Hanya owner bisa delete file-nya sendiri

File Validation ​

  • Type checking via MIME type
  • Extension whitelist
  • Size limit
  • Malware scan (via R2)

🐛 Troubleshooting Upload ​

MasalahSolusi
"File too large"Compress file atau resize image
"Invalid file type"Check allowed types di atas
"Upload failed"Check R2 credentials di .env
"Image not showing"Check R2_PUBLIC_URL benar
"403 Forbidden"Bucket public access belum enable

💡 Best Practices ​

Untuk Developer ​

  1. Always validate file type dan size
  2. Use unique filenames (timestamp + random)
  3. Organize by user atau folder
  4. Delete old files saat update avatar

Untuk User ​

  1. Compress images sebelum upload (faster)
  2. Use WebP jika bisa (smaller size)
  3. Avatar: Gunakan square image untuk hasil terbaik

📁 Files Terkait ​

src/
├── lib/
│   ├── image/
│   │   └── convert.ts       # WebP conversion
│   └── storage/
│       └── r2.ts            # R2 helpers
└── routes/
    └── api/
        └── upload/
            ├── image/+server.ts     # Image upload
            └── presign/+server.ts   # Presigned URL

📖 Lanjutan ​

SvelteKit Cloudflare Starter - Build Fast, Deploy Everywhere 🚀