Saltar al contenido principal

Capacitor Guía de manejo de archivos: Leer, escribir, elegir, compartir

Guía de manejo de archivos Capacitor : leer y escribir archivos, elegir directorios, seleccionar, mostrar, abrir, compartir y descargar y subir archivos en iOS y Android.

Guía de manejo de archivos Capacitor : leer, escribir, seleccionar, compartir

El manejo de archivos Capacitor se reduce a unos pocos bloques de construcción: @capacitor/filesystem para leer y escribir archivos en directorios de la aplicación Capacitor.convertFileSrc para mostrarlos, un selector para importar archivos de usuario, y plugins nativos para descargar, subir, abrir y compartir. Esta guía muestra cada uno de ellos con Capacitor 8 code, explica qué directorio utilizar en iOS y Android, y cubre los trampas de memoria y permisos que causan la mayoría de los errores de archivo.

La herramienta de manejo de archivos

Tarea Plugin
Read, write, list, copy, delete in app storage @capacitor/filesystem
Mostrar un archivo local en <img>, <video>, <iframe> Capacitor.convertFileSrc (núcleo)
Deje al usuario elegir archivos o una carpeta @capgo/capacitor-file-picker
Descargar con progreso @capacitor/file-transfer o @capgo/capacitor-downloader para descargas de fondo, pausables
Subir con progreso @capacitor/file-transfer o @capgo/capacitor-uploader para subir archivos de fondo
Compartir un archivo o guardar en Descargas @capgo/capacitor-file-sharer o @capacitor/share
Abrir un archivo en otra aplicación @capacitor-community/file-opener
Comprimir imágenes @capgo/capacitor-file-compressor
Comprimir imágenes @capgo/capacitor-zip

Instale el plugin principal primero:

bun add @capacitor/filesystem
bunx cap sync

Instale el plugin de base primero:

Elige el directorio correcto directoryElige el incorrecto es la causa más común de archivos perdidos y aplicaciones rechazadas.

Directory iOS location Ubicación de iOS Resguardado Usar para
Data Documents Directorio de archivos de la aplicación (/data/data/<pkg>/files) iOS iCloud, Android Copia de Seguridad de Auto Datos del usuario que pertenecen a la aplicación
Documents Documents (igual que Data) Public Documents carpeta Sí Evitar en Android 11+, ver abajo
Library Library Directorio de archivos de la aplicación iOS sí Archivos de soporte de la aplicación, bases de datos
LibraryNoCloud Library/NoCloud Directorio de archivos de la aplicación No Contenido grande, re-descargable
Cache Library/Caches Directorio de caché de la aplicación No Temporary files, can be wiped by the OS
External Documents Directorio de archivos externos de la aplicación No Archivos grandes de la aplicación en Android, eliminados al desinstalar
ExternalStorage Documents Raíz de almacenamiento compartido n/a Sólo legado, no accesible en Android 11+

Reglas de dedo:

  • Contenido de medios re-descargable grande (offline videos, map tiles) se almacenan LibraryNoCloudApple rechaza aplicaciones que almacenan contenido descargable grande en carpetas respaldadas por iCloud, como se describe en las Directrices de almacenamiento de datos de iOS.
  • Archivos temporales (los exports que compartas una vez, miniaturas) van en Cache. Nunca almacene la única copia de datos del usuario allí.
  • Archivos que el usuario debe encontrar más tarde fuera de la aplicación No pertenecen a ninguna carpeta de la aplicación. Guardelos a través de la hoja de compartir, MediaStore Descargas, o el selector de archivos del sistema. Consulte nuestra guía a Almacenamiento de Android escogido en Capacitor.

Escrbir un archivo

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,
});

La encoding La opción decide cómo data se interpreta. Con Encoding.UTF8, la cadena se escribe como texto. Sin ella, las plataformas nativas decodifican data como base64 y escriben bytes crudos. Olvidar esto es el clásico ‘mi PDF está corrupto’.

Para agregar a un archivo existente, como un registro, utilice appendFile con las mismas opciones.

Leer un archivo

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,
});

Compruebe si existe un archivo con stat, que rechaza cuando el archivo no existe:

async function exists(path: string) {
  try {
    await Filesystem.stat({ path, directory: Directory.Data });
    return true;
  } catch {
    return false;
  }
}

Leer archivos grandes en lotes

readFile devuelve el archivo completo como una cadena base64. Para un video de 200 MB significa cientos de MB de cadenas en memoria JS. readFileInChunks en lugar de eso:

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
  },
);

Mejor aún, evite mover los bytes a través de JS en absoluto. La mayoría de las tareas de 'leer un gran archivo' en realidad son 'subirlo' o 'mostrarlo', y ambos tienen rutas nativas debajo.

Listar, copiar, mover y eliminar

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 y rename aceptar toDirectory para moverse entre directorios, por ejemplo desde Cache para Data después de completar un descarga. También aceptan rutas absolutas file:// rutas cuando omitas directory, que es cómo importar archivos devueltos por otros plugins.

Muestra un archivo en la WebView

Jamás cargue imágenes o videos como URLs de datos base64 si puede evitarlo. Convirtiendo la ruta nativa a una URL servida por el servidor 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, el resultado es similar a capacitor://localhost/_capacitor_file_/..., en Android https://localhost/_capacitor_file_/.... Funciona para <img>, <video>, <audio>, y fetch(), lo que significa que también puedes leer un archivo como un ArrayBuffer sin base64:

const buffer = await fetch(Capacitor.convertFileSrc(uri)).then((r) => r.arrayBuffer());

Almacena rutas, no URLs convertidas. La forma convertida solo es válida para la sesión de la aplicación actual.

Selecciona archivos desde el dispositivo

El selector del sistema da al usuario control y no necesita permiso de almacenamiento en Android 13+ o 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);
}

Existen también pickImages, pickVideos, pickMedia y pickDirectory, además convertHeicToJpeg en iOS. En iOS, types solo acepta tipos MIME, no extensiones.

Los archivos seleccionados pueden residir en una ubicación temporal o detrás de un content:// URI que solo permanece legible durante un tiempo. Si necesita el archivo más tarde, copie en su propio directorio de inmediato con Filesystem.copy.

Descargar archivos

Con progreso: @capacitor/transferencia-de-archivo

Filesystem.downloadFile Se ha descontinuado en Filesystem 8. La reemplazo transmite la respuesta directamente a disco:

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 segundo plano: @capgo/descargador-capacitor

Para archivos grandes que deben seguir descargándose cuando el usuario abandone la aplicación, y que pueden ser pausados y reanudados, utilice el descargador Capgo, que se basa en DownloadManager en Android y segundo plano URLSession en 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 relativo destination se resuelve a la carpeta de archivos externos del aplicación en Android y Documents la misma carpeta en iOS, los lugares mismos donde Directory.External.

Subir archivos

No lea un archivo en base64 solo para enviarlo. Ambas opciones de subida leen desde el disco nativamente:

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);

Para subidas que deben sobrevivir a que la aplicación se ponga en segundo plano (videos, subidas en batch de fotos), utilice @capgo/capacitor-uploaderque se ejecuta en segundo plano URLSession en iOS y un servicio de subida con una notificación de progreso en 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 para almacenamiento de objetos son el patrón más confiable para archivos grandes: tu API firma la URL, y el dispositivo sube directamente al almacenamiento.

Compartir o exportar un archivo

Para permitir que el usuario envíe un archivo a otra aplicación o lo guarde en un lugar donde pueda encontrarlo:

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',
});

El compartidor de archivos Capgo copia el archivo en su propia carpeta de caché y lo sirve a través de un servidor dedicado. FileProvider, por lo tanto no necesitas editar file_paths.xmlCon la versión oficial @capacitor/share, Android solo puede compartir desde la carpeta de caché a menos que agregues otras carpetas a android/app/src/main/res/xml/file_paths.xml.

Abrir un archivo en otra aplicación

bun add @capacitor-community/file-opener
bunx cap sync
import { FileOpener } from '@capacitor-community/file-opener';

await FileOpener.open({ filePath: uri, contentType: 'application/pdf' });

En iOS, esto abre una vista previa de Quick Look. En Android, abre la aplicación por defecto para el tipo MIME o muestra un selector. Si ninguna aplicación puede manejar el tipo, la llamada rechaza, así que atrapa la excepción y ofrece compartir en su lugar

Recetas de archivos comunes

Generar un PDF: renderizar HTML con @capgo/capacitor-pdf-generator o constrúyelo en JS con pdf-lib, luego escribe la salida base64 con writeFileNuestra tutorial de escaneo a PDF muestra el flujo completo.

Quitar GPS de una foto antes de subirla: @capgo/capacitor-file-compressor elimina los metadatos EXIF en todas las plataformas mientras se redimensiona.

Redimensiona o convierte una imagen.: el mismo compresor maneja ancho, alto, calidad y formato de salida, incluyendo HEIC a JPEG.

Bundle muchos archivos.: zip una carpeta con @capgo/capacitor-zip y sube un archivo en lugar de cientos de solicitudes.

Soporte web

@capacitor/filesystem funciona en la web utilizando IndexedDB, por lo que tu code se ejecuta en el navegador durante el desarrollo. Ten en cuenta las siguientes diferencias: las lecturas binarias devuelven un Blob, los archivos solo existen en el perfil del navegador, y las cuotas de almacenamiento son mucho más bajas. Para compilaciones web, prefiere URL.createObjectURL(blob) para la visualización.

Troubleshooting

“El archivo no existe”: mezclaste directorios, o pasaste una ruta absoluta junto con un directory: Utiliza uno u otro.

Archivos binarios dañados: escribiste base64 con Encoding.UTF8: Elimina la codificación.

La aplicación se bloquea con archivos grandes: base64 a través del puente. Utiliza trozos, transferencia de archivos, o fetch(convertFileSrc(uri)).

La imagen no se muestra en Android: utilizaste una file:// Convertirlo directamente a la URL. Capacitor.convertFileSrc.

Failed to find configured root When compartiendo en Android: el archivo está fuera de los caminos en file_paths.xml. Utilice el compartidor de archivos Capgo o copie a Cache primero.

Los archivos desaparecen en iOS: estaban en Cache, que iOS elimina bajo presión de almacenamiento.

Rechazo de la App Store para almacenamiento en iCloud: contenido descargable grande en Data o Documents. Move it to LibraryNoCloud.

Próximos pasos

La mayoría de la lógica de archivo, como dónde almacenar cosas, reglas de reintento y nombres, viven en JavaScript y se pueden ajustar con Capgo actualizaciones en vivo después de la liberación. Para el lado Android de almacenamiento compartido y permisos, continúa con nuestra guía de almacenamiento en ámbitoy consulta los documentos del selector de archivos para cada opción de selector.

Actualizaciones en vivo para Capacitor aplicaciones

Cuando haya un error en la capa de web, envíe la corrección a través de Capgo en lugar de esperar días para la aprobación de la tienda de aplicaciones. Los usuarios obtienen la actualización en segundo plano mientras que los cambios nativos siguen en el camino de revisión normal.

Últimas noticias de nuestro Blog

Capgo le da las mejores perspectivas que necesita para crear una aplicación móvil verdaderamente profesional.