La gestion des fichiers Capacitor se résume à quelques blocs de construction : @capacitor/filesystem to read and write files in app directories, Capacitor.convertFileSrc pour les afficher, un sélecteur pour importer des fichiers utilisateur, et des plugins natifs pour télécharger, télécharger, ouvrir et partager. Ce guide montre chaque une avec Capacitor 8 code, explique quel répertoire utiliser sur iOS et Android, et couvre les pièges de la mémoire et des autorisations qui causent la plupart des bugs de fichiers.
La boîte à outils de gestion de fichiers
| Tâche | Plugin |
|---|---|
| Read, write, list, copy, delete in app storage | @capacitor/filesystem |
Afficher un fichier local dans <img>, <video>, <iframe> |
Capacitor.convertFileSrc (noyau) |
| Let the user pick files or a folder | @capgo/capacitor-file-picker |
| Télécharger avec progression | @capacitor/file-transfer ou @capgo/capacitor-downloader pour des téléchargements de fond, arrêtés |
| Télécharger avec progression | @capacitor/file-transfer ou @capgo/capacitor-uploader pour les téléchargements en arrière-plan |
| Share a file or save it to Downloads | @capgo/capacitor-file-sharer ou @capacitor/share |
| ouvrir un fichier dans une autre application | @capacitor-community/file-opener |
| Compresser les images | @capgo/capacitor-file-compressor |
| Compresser et décompresser | @capgo/capacitor-zip |
Installez le plugin de base en premier :
bun add @capacitor/filesystem
bunx cap sync
Choisissez le bon répertoire
Chaque appel au système de fichiers prend un directorySélectionner le mauvais peut être la principale cause de fichiers perdus et d'applications rejetées.
Directory |
Emplacement de l'appareil iOS | Emplacement de l'appareil Android | Protégé | Utiliser pour |
|---|---|---|---|---|
Data |
Documents |
Dossier des fichiers de l'application (/data/data/<pkg>/files) |
iOS iCloud, Android Sauvegarde Auto | Les données de l'utilisateur que l'application possède |
Documents |
Documents (même que Data) |
Dossier public Documents Dossier |
Oui | Éviter sur Android 11+, voir ci-dessous |
Library |
Library |
Dossier des fichiers de l'application | iOS oui | Fichiers d'application, bases de données |
LibraryNoCloud |
Library/NoCloud |
Répertoire des fichiers de l'application | Non | Contenu volumineux, redownloadable |
Cache |
Library/Caches |
Répertoire de cache de l'application | Non | Temporary files, can be wiped by the OS |
External |
Documents |
Répertoire des fichiers externes de l'application | Non | Large app files on Android, deleted on uninstall |
ExternalStorage |
Documents |
Racine du stockage partagé | n/a | Seulement pour les anciens, non accessible sur Android 11+ |
Règles de doigté :
- Fichiers de médias redéchargeables importants (vidéos hors ligne, tuiles de cartes) y va
LibraryNoCloudApple rejette les applications qui mettent du contenu téléchargeable important dans des dossiers iCloud, comme le décrit les lignes directrices de stockage de données iOS. - Fichiers temporaires (exportez une fois, les miniatures s'y trouvent)
CacheN'entreposez jamais la seule copie de données utilisateur là. - Files the user should find later outside your app do not belong in an app directory at all. Save them through the share sheet, MediaStore Downloads, or the system file picker. See our guide to Stockage Android scoping dans Capacitor.
Écrire un fichier
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,
});
Le encoding l'option détermine comment data est interprété. Avec Encoding.UTF8, la chaîne est écrite en texte. Sans elle, les plateformes natives décodent data en base64 et écrivent les octets bruts. Oublier cela est le classique « mon PDF est corrompu » bug.
Pour ajouter à un fichier existant, tel qu'un journal, utilisez appendFile avec les mêmes options.
Lire un fichier
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,
});
Vérifiez si un fichier existe avec stat, qui rejette lorsque le fichier manque :
async function exists(path: string) {
try {
await Filesystem.stat({ path, directory: Directory.Data });
return true;
} catch {
return false;
}
}
Lire de grands fichiers en tranches
readFile renvoie tout le fichier sous forme d'une chaîne base64. Pour un vidéo de 200 MB, cela signifie des centaines de MB de chaînes en mémoire JS. readFileInChunks fluent le flux au lieu :
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
},
);
Mieux encore, évitez de déplacer les octets à travers JS au tout. La plupart des tâches « lire un grand fichier » sont vraiment « l'envoyer » ou « l’afficher », et les deux ont des chemins natifs en dessous.
Lister, copier, déplacer et supprimer
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 et rename accept toDirectory Pour naviguer entre les dossiers, par exemple à partir de Cache to Data après la fin du téléchargement. Ils acceptent également des chemins absolus file:// chemins absolus lorsque vous omittrez directorylesquels est comment vous importez les fichiers retournés par d'autres plugins.
Afficher un fichier dans le WebView
Ne jamais charger les images ou les vidéos en tant que données URL base64 si vous pouvez l'éviter. Convertissez le chemin natif en URL servie par le serveur local de Capacitor :
import { Capacitor } from '@capacitor/core';
const { uri } = await Filesystem.getUri({ path: 'images/logo.png', directory: Directory.Data });
img.src = Capacitor.convertFileSrc(uri);
On iOS, le résultat ressemble à capacitor://localhost/_capacitor_file_/..., sur Android https://localhost/_capacitor_file_/.... Il fonctionne pour <img>, <video>, <audio>, et fetch()Pouvez-vous également lire un fichier comme un ArrayBuffer sans base64 :
const buffer = await fetch(Capacitor.convertFileSrc(uri)).then((r) => r.arrayBuffer());
Enregistrez les chemins, pas les URL converties. La forme convertie n'est valide que pour la session de l'application en cours.
Sélectionnez des fichiers sur le dispositif
Le sélecteur système donne au utilisateur le contrôl’et n'a pas besoin de la permission de stockage sur Android 13+ ou 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);
}
Il existe également pickImages, pickVideos, pickMedia et pickDirectory, plus convertHeicToJpeg sur iOS. Sur iOS, types accepte que les types MIME, pas les extensions.
Les fichiers sélectionnés peuvent vivre dans un emplacement temporaire ou derrière un content:// URI qui n'est que lisible pendant un certain temps. Si vous avez besoin du fichier plus tard, copiez-le dans votre propre répertoire dès que possible avec Filesystem.copy.
Téléchargez des fichiers
Avec progression : @capacitor/transfert-de-fichier
Filesystem.downloadFile est obsolète dans Filesystem 8. La remplaçante envoie directement la réponse sur le disque :
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();
En arrière-plan : @capgo/capacitor-téléchargement
Pour les fichiers importants qui doivent continuer à se télécharger lorsque l'utilisateur quitte l'application, et qui peuvent être suspendus et repris, utilisez le téléchargeur Capgo, qui repose sur DownloadManager en arrière-plan sur Android et URLSession sur 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
});
Un élément relatif destination se traduit par le répertoire des fichiers externes de l'application sur Android et le Documents répertoire sur iOS, les mêmes endroits que Directory.External.
Télécharger des fichiers
Ne lisez pas un fichier en base64 juste pour le transmettre. Les deux options de téléchargement lisent depuis le disque nativement :
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);
Télécharger des fichiers qui doivent survivre à l'application qui passe en arrière-plan (vidéos, téléchargements de photos en batch), utilisez @capgo/capacitor-uploaderqui fonctionne en arrière-plan URLSession sur iOS et un service de téléchargement avec une notification de progression sur 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 URLs vers le stockage objet sont le modèle le plus fiable pour les grands fichiers : votre API signe l'URL, et le dispositif télécharge directement vers le stockage.
Partager ou exporter un fichier
Permettre à l'utilisateur d'envoyer un fichier à une autre application ou de le sauvegarder où il peut le trouver :
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',
});
Le partageur de fichiers Capgo copie le fichier dans son propre dossier de cache et le sert à travers un canal dédié. FileProvider, vous n'avez donc pas besoin de modifier file_paths.xmlAvec l'official @capacitor/share, Android ne peut partager que depuis le dossier de cache à moins que vous n'ajoutiez d'autres dossiers android/app/src/main/res/xml/file_paths.xml.
Ouvrir un fichier dans une autre application
bun add @capacitor-community/file-opener
bunx cap sync
import { FileOpener } from '@capacitor-community/file-opener';
await FileOpener.open({ filePath: uri, contentType: 'application/pdf' });
Sur iOS, cela ouvre une prévisualisation Quick Look. Sur Android, cela ouvre l'application par défaut pour le type MIME ou propose un choix. Si aucune application ne peut gérer le type, l'appel est rejeté, alors attrapez-l’et proposez la partage à la place.
Recettes de fichiers courantes
Générer un PDF: afficher l'HTML avec @capgo/capacitor-pdf-generator ou construisez-l’en JS avec pdf-lib, puis écrivez la sortie base64 avec writeFileNotre tutoriel de scan à PDF affiche la trajectoire complète.
Supprime le GPS d'une photo avant l'upload: @capgo/capacitor-file-compressor removes EXIF metadata on every platform while resizing.
Redimensionne ou convertit une image: le même compresseur gère la largeur, la hauteur, la qualité et le format de sortie, y compris HEIC en JPEG.
Bundle de nombreux fichiers: archive un dossier avec @capgo/capacitor-zip et télécharge un seul archive au lieu de centaines de requêtes.
Support Web
@capacitor/filesystem travaillent sur le web en utilisant IndexedDB, donc votre code s'exécute dans le navigateur pendant le développement. Différences à garder à l'esprit : les lectures binaires retournent un Blobseuls les fichiers vivent dans le profil du navigateur, et les quotas de stockage sont beaucoup plus bas. Pour les builds web, préférez URL.createObjectURL(blob) pour la mise en page.
Troubleshooting
“Le fichier n'existe pas”: vous avez mélangé des dossiers, ou passé un chemin absolu avec un directory: utilisez l'un ou l'autre.
Fichiers binaires corrompus: vous avez écrit base64 avec Encoding.UTF8: supprimez l'encodage.
L'application s'arrête avec des fichiers volumineux: base64z par le pont. Utilisez des tranches, du transfert de fichiers, ou fetch(convertFileSrc(uri)).
L'image ne s'affiche pas sur Android: vous avez utilisé un file:// Convertez-le directement. Convertissez-l’avec Capacitor.convertFileSrc.
Failed to find configured root Quand vous partagez sur AndroidLe fichier est en dehors des chemins autorisés. file_paths.xmlUtilisez le partageur de fichiers Capgo ou copiez vers Cache premier.
Les fichiers disparaissent sur iOS: ils étaient dans Cache, qui est supprimé par iOS sous pression de stockage.
Rejet de l'App Store pour le stockage iCloud: contenu téléchargeable volumineux Data ou DocumentsDéplacez-le LibraryNoCloud.
Étapes suivantes
La plupart de la logique des fichiers, comme où stocker les choses, les règles de réessai et les noms, vivent dans JavaScript et peuvent être ajustées avec Capgo mises à jour en direct après la mise à jour. Pour la partie Android de la stockage partagé et des permissions, continuez avec notre guide de stockage scopinget voyez les docs du sélecteur de fichiers pour chaque option de sélecteur.