Pengelolaan file Capacitor terdiri dari beberapa blok dasar. @capacitor/filesystem untuk membaca dan menulis file di direktori aplikasi, Capacitor.convertFileSrc to display them, a picker to import user files, and native plugins to download, upload, open and share. This guide shows each one with Capacitor 8 code, explains which directory to use on iOS and Android, and covers the memory and permission traps that cause most file bugs.
Peralatan Pengelolaan File
| Tugas | Plugin |
|---|---|
| Baca, tulis, daftar, salin, hapus di penyimpanan aplikasi | @capacitor/filesystem |
Tampilkan file lokal di <img>, <video>, <iframe> |
Capacitor.convertFileSrc (core) |
| Pilih file atau folder pengguna | @capgo/capacitor-file-picker |
| Mendownload dengan progress | @capacitor/file-transfer atau @capgo/capacitor-downloader for background, pausable downloads |
| Unggah dengan progress | @capacitor/file-transfer atau @capgo/capacitor-uploader untuk mengunggah latar belakang |
| Bagikan file atau simpan ke Downloads | @capgo/capacitor-file-sharer atau @capacitor/share |
| Buka file di aplikasi lain | @capacitor-community/file-opener |
| Mengompres gambar | @capgo/capacitor-file-compressor |
| Mengompres dan mengekstrak file zip | @capgo/capacitor-zip |
Pasang plugin inti terlebih dahulu:
bun add @capacitor/filesystem
bunx cap sync
Pilih direktori yang tepat
Setiap panggilan Filesystem memerlukan directory . Memilih yang salah adalah penyebab paling umum dari kehilangan file dan aplikasi ditolak.
Directory |
lokasi iOS | Android Lokasi | Ditambahkan ke | Gunakan untuk |
|---|---|---|---|---|
Data |
Documents |
Folder file aplikasi (/data/data/<pkg>/files) |
iOS iCloud, Android Otomatis Backup | Data pengguna yang dimiliki aplikasi |
Documents |
Documents (sama seperti Data) |
Publik Documents Folder |
Ya | Perbandingan dengan Native |
Library |
Library |
Direktori File Aplikasi | Ya iOS | File-file dukungan aplikasi, basis data |
LibraryNoCloud |
Library/NoCloud |
Direktori file aplikasi | Tidak | Konten besar, dapat diunduh ulang |
Cache |
Library/Caches |
Direktori cache aplikasi | Tidak | File sementara, dapat dihapus oleh sistem operasi |
External |
Documents |
Direktori file eksternal aplikasi | Tidak | File aplikasi besar di Android, dihapus saat aplikasi di-uninstall |
ExternalStorage |
Documents |
Root penyimpanan bersama | n/a | Khusus Legacy, tidak dapat diakses di Android 11+ |
Hal-hal yang perlu diingat:
- Media besar yang dapat diunduh ulang (video offline, tile peta) masuk ke
LibraryNoCloud. Apple menolak aplikasi yang memasukkan konten unduh ulang besar ke folder iCloud, seperti yang dijelaskan dalam iOS Data Storage Guidelines. - File sementara (ekspor yang Anda bagikan sekali, thumbnail) masuk ke
Cache. Jangan menyimpan data pengguna tunggal di sana. - File yang pengguna harus temukan nanti di luar aplikasi tidak boleh masuk ke direktori aplikasi. Simpan melalui sheet berbagi, MediaStore Downloads, atau pilih file sistem. Lihat panduan kami tentang penyimpanan Android yang terbatas di Capacitor.
Membuat file
import { Filesystem, Directory, Encoding } from '@capacitor/filesystem';
// Text file
await Filesystem.writeFile({
path: 'notes/today.txt',
data: 'Hello from Capacitor',
directory: Directory.Data,
encoding: Encoding.UTF8,
recursive: true, // create notes/ if missing
});
// JSON
await Filesystem.writeFile({
path: 'settings.json',
data: JSON.stringify({ theme: 'dark' }),
directory: Directory.Data,
encoding: Encoding.UTF8,
});
// Binary file: pass base64 and no encoding
await Filesystem.writeFile({
path: 'images/logo.png',
data: base64Png,
directory: Directory.Data,
recursive: true,
});
File ini encoding Opsi ini menentukan bagaimana data ditafsirkan. Dengan Encoding.UTF8, string ditulis sebagai teks. Tanpa itu, platform asli mengodekan data sebagai base64 dan menulis byte mentah. Lupa ini adalah bug klasik “PDF saya rusak”.
Tambahkan ke file yang sudah ada, seperti log, menggunakan appendFile dengan opsi yang sama.
Baca file
const { data } = await Filesystem.readFile({
path: 'settings.json',
directory: Directory.Data,
encoding: Encoding.UTF8,
});
const settings = JSON.parse(data as string);
// Binary: returns base64 on native, a Blob on web
const image = await Filesystem.readFile({
path: 'images/logo.png',
directory: Directory.Data,
});
Periksa apakah sebuah file ada statPeriksa apakah file ada dengan
async function exists(path: string) {
try {
await Filesystem.stat({ path, directory: Directory.Data });
return true;
} catch {
return false;
}
}
, yang menolak ketika file hilang:
readFile Mengembalikan seluruh file sebagai satu string base64. Ini berarti ratusan MB string di dalam memori JS untuk sebuah video 200 MB. readFileInChunks mengalirkannya secara berurutan:
await Filesystem.readFileInChunks(
{ path: 'videos/clip.mp4', directory: Directory.Data, chunkSize: 1024 * 1024 },
(chunk, err) => {
if (err) return console.error(err);
if (chunk === null) return console.log('done');
processChunk(chunk.data); // base64 chunk
},
);
Better still, avoid moving the bytes through JS at all. Most “read a big file” tasks are really “upload it” or “display it”, and both have native paths below.
Daftar, salin, pindahkan dan hapus
const { files } = await Filesystem.readdir({ path: 'notes', directory: Directory.Data });
for (const f of files) console.log(f.name, f.type, f.size, f.mtime);
await Filesystem.mkdir({ path: 'archive', directory: Directory.Data, recursive: true });
await Filesystem.copy({
from: 'notes/today.txt',
to: 'archive/today.txt',
directory: Directory.Data,
});
await Filesystem.rename({
from: 'archive/today.txt',
to: 'archive/2026-10-01.txt',
directory: Directory.Data,
});
await Filesystem.deleteFile({ path: 'notes/today.txt', directory: Directory.Data });
await Filesystem.rmdir({ path: 'notes', directory: Directory.Data, recursive: true });
copy and rename unggah toDirectory Untuk berpindah antara direktori, misalnya dari Cache tampilkan Data , dan kedua-duanya memiliki jalur asli di bawah. file:// Daftar, salin, pindahkan, dan hapus directoryyang digunakan untuk mengimport file-file yang dikembalikan oleh plugin lain.
menerima pindah antar direktori, misalnya dari kepada .
Jangan pernah memuat gambar atau video sebagai URL data base64 jika bisa dihindari. Konversi jalur asli ke URL yang disajikan oleh Capacitor’s server lokal:
import { Capacitor } from '@capacitor/core';
const { uri } = await Filesystem.getUri({ path: 'images/logo.png', directory: Directory.Data });
img.src = Capacitor.convertFileSrc(uri);
On iOS hasilnya seperti capacitor://localhost/_capacitor_file_/..., pada Android https://localhost/_capacitor_file_/.... Ini berfungsi untuk <img>, <video>, <audio>, dan fetch(), yang berarti Anda juga dapat membaca file sebagai ArrayBuffer tanpa base64:
const buffer = await fetch(Capacitor.convertFileSrc(uri)).then((r) => r.arrayBuffer());
Simpan jalur, bukan URL yang telah dikonversi. Bentuk yang dikonversi hanya valid untuk sesi aplikasi saat ini.
Pilih file dari perangkat
Pemilih sistem memberikan kontrol kepada pengguna dan tidak memerlukan izin penyimpanan pada Android 13+ atau iOS:
bun add @capgo/capacitor-file-picker
bunx cap sync
import { CapgoFilePicker } from '@capgo/capacitor-file-picker';
const { files } = await CapgoFilePicker.pickFiles({
types: ['application/pdf', 'image/*'],
limit: 5,
readData: false, // keep false for anything bigger than a few MB
});
for (const file of files) {
console.log(file.name, file.mimeType, file.size, file.path);
}
Terdapat juga pickImages, pickVideos, pickMedia dan pickDirectorydan plus convertHeicToJpeg di iOS. Di iOS, types hanya menerima jenis MIME, bukan ekstensi.
File yang dipilih mungkin berada di lokasi sementara atau di belakang content:// URI yang hanya dapat dibaca selama beberapa waktu. Jika Anda membutuhkan file tersebut kemudian, salinlah ke direktori Anda sendiri segera dengan Filesystem.copy.
Unduh file
Dengan kemajuan: @capacitor/transfer-file
Filesystem.downloadFile telah ditinggalkan dalam Filesystem 8. Penggantinya mengalirkan respons langsung ke disk:
bun add @capacitor/file-transfer
bunx cap sync
import { FileTransfer } from '@capacitor/file-transfer';
import { Directory, Filesystem } from '@capacitor/filesystem';
const { uri } = await Filesystem.getUri({ path: 'downloads/report.pdf', directory: Directory.Data });
const listener = await FileTransfer.addListener('progress', (p) => {
if (p.lengthComputable) setProgress(p.bytes / p.contentLength);
});
await FileTransfer.downloadFile({
url: 'https://example.com/report.pdf',
path: uri,
progress: true,
headers: { Authorization: `Bearer ${token}` },
});
await listener.remove();
Dalam latar belakang: @capgo/capacitor-downloader
Untuk file besar yang harus terus mengunduh ketika pengguna meninggalkan aplikasi, dan dapat dihentikan dan dilanjutkan, gunakan downloader Capgo, yang bergantung pada DownloadManager di Android dan latar belakang URLSession di iOS:
import { CapacitorDownloader } from '@capgo/capacitor-downloader';
await CapacitorDownloader.addListener('downloadProgress', ({ id, progress }) => {
console.log(id, progress);
});
await CapacitorDownloader.addListener('downloadCompleted', ({ id }) => {
console.log('done', id);
});
await CapacitorDownloader.download({
id: 'course-video-12',
url: 'https://cdn.example.com/course/12.mp4',
destination: 'videos/12.mp4',
network: 'wifi-only',
notification: 'progress', // Android
});
Ambil relatif destination mengarah ke direktori file eksternal aplikasi di Android dan direktori Documents yang sama seperti direktori Directory.External.
Upload file
Tidak membaca file ke base64 hanya untuk mengirimkannya. Kedua opsi unggah membaca dari disk secara native:
import { FileTransfer } from '@capacitor/file-transfer';
const result = await FileTransfer.uploadFile({
url: 'https://api.example.com/upload',
path: uri, // full file:// path
fileKey: 'file',
mimeType: 'application/pdf',
headers: { Authorization: `Bearer ${token}` },
progress: true,
});
console.log(result.responseCode, result.bytesSent);
For unggah yang harus bertahan ketika aplikasi pergi ke latar belakang (video, unggah foto batch), gunakan @capgo/capacitor-uploaderyang berjalan di latar belakang URLSession di iOS dan layanan unggah dengan pemberitahuan progress di Android:
import { Uploader } from '@capgo/capacitor-uploader';
const { id } = await Uploader.startUpload({
filePath: uri,
serverUrl: 'https://api.example.com/upload',
method: 'PUT', // binary body, ideal for presigned S3 or R2 URLs
mimeType: 'video/mp4',
});
Presigned PUT untuk penyimpanan objek adalah pola yang paling dapat diandalkan untuk file besar: API Anda menandatangani URL, dan perangkat mengunggah langsung ke penyimpanan.
Bagikan atau ekspor file
Untuk memungkinkan pengguna mengirimkan file ke aplikasi lain atau menyimpannya di tempat yang mereka bisa temukan.
import { FileSharer } from '@capgo/capacitor-file-sharer';
await FileSharer.share({
filename: 'report.pdf',
path: uri,
contentType: 'application/pdf',
});
// Android: write to Downloads via MediaStore. iOS: opens the share sheet ("Save to Files")
await FileSharer.save({
filename: 'report.pdf',
path: uri,
contentType: 'application/pdf',
});
File penerus Capgo menyalin file ke folder cache sendiri dan menyajikannya melalui jalur dedikasi FileProviderJadi, Anda tidak perlu mengedit. file_paths.xml. Dengan resmi @capacitor/shareAndroid hanya dapat berbagi dari folder cache kecuali Anda menambahkan folder lain ke android/app/src/main/res/xml/file_paths.xml.
Buka file di aplikasi lain
bun add @capacitor-community/file-opener
bunx cap sync
import { FileOpener } from '@capacitor-community/file-opener';
await FileOpener.open({ filePath: uri, contentType: 'application/pdf' });
Pada iOS ini membuka tampilan Quick Look. Pada Android membuka aplikasi default untuk MIME type atau menampilkan pilihan. Jika tidak ada aplikasi yang dapat menangani jenisnya, panggilan menolak, jadi tangkap dan tawarkan berbagi alih-alih
Resep file umum
Generate PDF: render HTML dengan @capgo/capacitor-pdf-generator atau bangunnya di JS dengan pdf-lib, kemudian tuliskan output base64 dengan writeFiledan tutorial scan ke PDF menunjukkan alur lengkap.
Stripping GPS dari foto sebelum unggah: @capgo/capacitor-file-compressor menghapus metadata EXIF di setiap platform saat mengubah ukuran.
Mengubah atau mengubah ukuran gambar: kompresor yang sama mengatur lebar, tinggi, kualitas, dan format keluaran, termasuk HEIC ke JPEG.
Mengemas banyak file: mengemas folder dengan @capgo/capacitor-zip dan mengunggah satu arsip daripada ratusan permintaan.
Dukungan Web
@capacitor/filesystem berfungsi di web menggunakan IndexedDB, sehingga aplikasi code Anda berjalan di browser selama pengembangan. Perbedaan yang perlu diingat: bacaan biner mengembalikan Blobfile hanya ada di profil browser, dan kuota penyimpanan jauh lebih rendah. Untuk build web, prefer URL.createObjectURL(blob) untuk menampilkan.
Pengaturan Masalah
“File tidak ada”: Anda campur direktori, atau melewati jalur absolut bersama dengan directoryGunakan salah satu atau yang lain.
File biner rusak: Anda menulis base64 dengan Encoding.UTF8Hapus kode encoding.
Aplikasi bermasalah dengan file besar: base64 melalui bridge. Gunakan chunk, file-transfer, atau fetch(convertFileSrc(uri)).
Gambar tidak ditampilkan di Android: Anda menggunakan file:// URL secara langsung. Konversi dengan Capacitor.convertFileSrc.
Failed to find configured root ketika berbagi di Android: file tersebut berada di luar jalur di file_paths.xmlgunakan pengguna file Capgo atau salin ke Cache first.
File hilang di iOS: mereka berada di Cache, yang iOS hapus karena tekanan penyimpanan.
Penolakan App Store untuk penyimpanan iCloud: konten download besar di Data atau DocumentsPindahkan ke LibraryNoCloud.
Langkah berikutnya
Sebagian besar logika file, seperti di mana Anda menyimpan hal-hal, aturan ulang, dan penamaan, hidup di JavaScript dan dapat disesuaikan dengan Capgo pembaruan hidup setelah rilis. Untuk sisi Android penyimpanan bersama dan izin, lanjutkan dengan panduan penyimpanan berskala , dan lihat dokumen pemilih fileuntuk setiap pilihan pemilih. Kredit artikel untuk setiap pilihan picker.