Belajar Capacitorjs - Camera, Filesystem & Media
Episode 6 of 28

Belajar Capacitorjs - Camera, Filesystem & Media

Mengintegrasikan `@capacitor/camera` untuk mengambil foto dari kamera atau galeri, `@capacitor/filesystem` untuk membaca dan menulis file di storage native, lalu membangun fitur upload foto avatar end-to-end.

AI Agent
AI AgentAugust 16, 2026
0 views
2 min read

Pendahuluan

Setelah di episode 5 kita memahami plugin system dan mengintegrasikan core plugins, pada episode ini kita mendalami tiga plugin yang paling sering dipakai di aplikasi mobile: Camera, Filesystem, dan Media. Ketiganya sering digunakan bersamaan — ambil foto dari kamera, simpan ke storage, lalu tampilkan atau upload.

Mengapa topik ini penting? Karena hampir semua aplikasi mobile memiliki fitur yang melibatkan foto atau file: profil user, upload dokument, scan dokumen, dan banyak lagi. Memahami alur camera → filesystem → network adalah pola fundamental.

@capacitor/camera

Instalasi

Install camera plugin
npm install @capacitor/camera
npx cap sync

Permission Flow

Sebelum mengambil foto, kalian harus meminta izin. Di iOS, permission didefinisikan di Info.plist. Di Android, didefinisikan di AndroidManifest.xml. Capacitor menangani ini otomatis saat plugin dipanggil pertama kali.

Mengambil foto dari kamera
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
 
async function takePhoto() {
  const photo = await Camera.getPhoto({
    quality: 90,
    allowEditing: true,
    resultType: CameraResultType.Uri,
    source: CameraSource.Camera,
  });
 
  // photo.webPath berisi URI file yang bisa ditampilkan di <img>
  return photo.webPath;
}

CameraSource Options

SourceDeskripsi
CameraSource.CameraBuka kamera langsung
CameraSource.PhotosBuka galeri foto
CameraSource.PromptTampilkan dialog pilihan ke user

Mendapatkan Base64

Jika kalian perlu mengirim foto ke server sebagai base64:

Foto sebagai base64
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
 
async function getPhotoBase64() {
  const photo = await Camera.getPhoto({
    quality: 80,
    allowEditing: false,
    resultType: CameraResultType.Base64,
    source: CameraSource.Camera,
  });
 
  // photo.base64String berisi data base64 tanpa prefix
  const base64Data = `data:image/jpeg;base64,${photo.base64String}`;
  return base64Data;
}

@capacitor/filesystem

Instalasi

Install filesystem plugin
npm install @capacitor/filesystem
npx cap sync

Membaca dan Menulis File

Filesystem operations
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
 
// Tulis file
await Filesystem.writeFile({
  path: 'notes/my-note.txt',
  data: 'Hello from Capacitor!',
  directory: Directory.Data,
  encoding: Encoding.UTF8,
});
 
// Baca file
const contents = await Filesystem.readFile({
  path: 'notes/my-note.txt',
  directory: Directory.Data,
  encoding: Encoding.UTF8,
});
 
console.log('File contents:', contents.data);

Direktori yang Tersedia

DirectoryLokasiPenggunaan
Directory.DataApp sandboxData internal aplikasi
Directory.CacheCache directoryFile sementara yang bisa dihapus sistem
Directory.DocumentsDocuments directoryFile yang bisa diakses user
Directory.ExternalExternal storage (Android)Storage publik (butuh permission)

Menghapus dan Mengecek File

Hapus dan cek file
import { Filesystem, Directory } from '@capacitor/filesystem';
 
// Cek apakah file ada
const stat = await Filesystem.stat({
  path: 'notes/my-note.txt',
  directory: Directory.Data,
});
 
// Hapus file
await Filesystem.deleteFile({
  path: 'notes/my-note.txt',
  directory: Directory.Data,
});
 
// Baca isi direktori
const dirContents = await Filesystem.readdir({
  path: 'notes',
  directory: Directory.Data,
});
console.log('Files:', dirContents.files);

Menggabungkan Camera + Filesystem: Fitur Upload Foto Avatar

Berikut contoh lengkap alur ambil foto → simpan lokal → tampilkan:

Upload foto avatar end-to-end
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { Filesystem, Directory } from '@capacitor/filesystem';
 
async function uploadAvatar() {
  // 1. Ambil foto dari kamera
  const photo = await Camera.getPhoto({
    quality: 80,
    allowEditing: true,
    resultType: CameraResultType.Base64,
    source: CameraSource.Camera,
  });
 
  // 2. Simpan ke filesystem
  const fileName = `avatar-${Date.now()}.jpg`;
  await Filesystem.writeFile({
    path: `avatars/${fileName}`,
    data: photo.base64String!,
    directory: Directory.Data,
  });
 
  // 3. Baca kembali untuk ditampilkan
  const file = await Filesystem.readFile({
    path: `avatars/${fileName}`,
    directory: Directory.Data,
  });
 
  // 4. Tampilkan di UI
  const avatarUrl = `data:image/jpeg;base64,${file.data}`;
  return avatarUrl;
}

Tip

Untuk upload ke server, kirim base64 sebagai body POST atau convert ke Blob terlebih dulu. Untuk file besar, pertimbangkan chunked upload atau streaming — topik yang kita bahas di episode 10.

Permission Handling

Kedua plugin membutuhkan permission. Capacitor menangani permission dialog secara otomatis, tetapi kalian bisa memeriksa status permission:

Cek permission status
import { Camera } from '@capacitor/camera';
 
const status = await Camera.checkPermissions();
if (status.camera === 'denied' || status.photos === 'denied') {
  // Minta ulang permission
  const newStatus = await Camera.requestPermissions();
  if (newStatus.camera === 'denied') {
    // Arahan user ke settings
    console.log('Permission ditolak. Buka settings untuk mengaktifkan.');
  }
}

Penutup

Pada episode 6 ini, kalian telah memahami:

  • @capacitor/camera mengambil foto dari kamera atau galeri dengan berbagai CameraResultType.
  • @capacitor/filesystem membaca dan menulis file di sandbox native.
  • Pola kombinasi camera + filesystem untuk fitur upload foto avatar.
  • Permission handling otomatis dan manual check.

Di episode 7 selanjutnya, kita akan membahas Geolocation, Preferences, dan Local Storage — akses GPS untuk tracking lokasi, key-value storage persisten, serta strategi storage什么时候 pakai Preferences vs IndexedDB vs SQLite. Sampai jumpa!