メインコンテンツへスキップ

Capacitor ファイル操作ガイド:読み込み、書き込み、選択、共有

Capacitor ファイル操作ガイド: iOSとAndroidでのファイルの読み書き、ディレクトリ選択、ファイルの選択・表示・オープン・共有・ダウンロード・アップロード。

Capacitor モバイルアプリでのファイルの読み書きと共有

Capacitor のファイル処理は、いくつかの基盤要素に集約されます: @capacitor/filesystem アプリディレクトリ内のファイルの読み書きには、 Capacitor.convertFileSrc 表示には、ユーザーファイルのインポートにはピッカー、ダウンロード・アップロード・開く・共有にはネイティブプラグインを使用します。本ガイドでは Capacitor 8 code を用いて各要素を解説し、iOS と Android で使用するディレクトリ、そして多くのファイル関連バグの原因となるメモリと権限の落とし穴について説明します。

ファイル処理のツールボックス

タスク プラグイン
アプリストレージでの読み書き、一覧表示、コピー、削除 @capacitor/filesystem
ローカルファイルの表示 <img>, <video>, <iframe> Capacitor.convertFileSrc (コア)
ユーザーがファイルまたはフォルダを選択 @capgo/capacitor-file-picker
進捗表示付きダウンロード @capacitor/file-transfer または @capgo/capacitor-downloader バックグラウンド、一時停止可能なダウンロードに
進捗表示付きアップロード @capacitor/file-transfer または @capgo/capacitor-uploader バックグラウンドアップロードに
ファイルを共有またはダウンロードに保存 @capgo/capacitor-file-sharer または @capacitor/share
別のアプリでファイルを開く @capacitor-community/file-opener
画像を圧縮 @capgo/capacitor-file-compressor
Zip 圧縮と解凍 @capgo/capacitor-zip

まずコアプラグインをインストールします:

bun add @capacitor/filesystem
bunx cap sync

適切なディレクトリを選択

すべての Filesystem 呼び出しには directoryが必要です。間違ったものを選ぶと、ファイルの消失やアプリの拒否につながる最も一般的な原因になります。

Directory iOS の保存場所 Android の保存場所 バックアップ対象 用途
Data Documents アプリファイルディレクトリ (/data/data/<pkg>/files) iOS iCloud、Android Auto Backup アプリが管理するユーザーデータ
Documents Documents (と同じ Data) パブリック Documents フォルダ はい Android 11以降は避ける(下記参照)
Library Library アプリファイルディレクトリ iOS: 可 アプリのサポートファイル、データベース
LibraryNoCloud Library/NoCloud アプリファイルディレクトリ いいえ 大容量で再ダウンロード可能なコンテンツ
Cache Library/Caches アプリキャッシュディレクトリ いいえ 一時ファイル(OSによって削除される可能性あり)
External Documents アプリ外部ファイルディレクトリ いいえ Androidの大容量アプリファイル(アンインストール時に削除)
ExternalStorage Documents 共有ストレージのルート なし レガシーのみ、Android 11以降ではアクセス不可

基本ルール:

  • 大容量の再ダウンロード可能なメディア (オフライン動画、マップタイルなど)を格納 LibraryNoCloud。Appleは、iOSデータストレージガイドラインに記載されているように、iCloudバックアップ対応フォルダに大容量の再ダウンロード可能なコンテンツを配置するアプリを拒否します。
  • 一時ファイル (一度共有するエクスポートやサムネイルなど)は Cache。ユーザーデータの唯一のコピーをそこに保存しないでください。
  • アプリ外で後からユーザーが見つけるべきファイル はアプリディレクトリに属しません。共有シート、MediaStore Downloads、またはシステムファイルピッカー経由で保存してください。 CapacitorにおけるAndroidのスコープ付きストレージ.

ファイルの書き込み

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

この encoding オプションは、 data の解釈を決めます。たとえば Encoding.UTF8なら、文字列はテキストとして書き込まれます。指定しない場合、ネイティブプラットフォームは data を base64 としてデコードし、生のバイト列を書き込みます。これを見落とすと「PDF が壊れている」という定番のバグになります。

ログなどの既存のファイルに追記するには、 appendFile を同じオプションで使います。

ファイルの読み込み

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

ファイルが存在するか確認するには statを使います。ファイルが存在しない場合は reject します:

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

大きなファイルをチャンクごとに読み込む

readFile ファイル全体を1つのbase64文字列として返します。200 MBの動画なら、JSメモリ上に数百MBの文字列が載ることになります。 readFileInChunks 代わりにストリームで処理します:

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

さらに良いのは、JSを経由してバイトを一切動かさないことです。「大きなファイルを読む」タスクのほとんどは実際には「アップロードする」か「表示する」で、どちらにも下記のネイティブな方法があります。

一覧表示、コピー、移動、削除

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 と rename 受け付けます toDirectory ディレクトリ間を移動するには、例えば次から Cache まで Data ダウンロード完了後にも使えます。また、絶対 file:// パスも受け付けます。省略した場合は directory、他のプラグインから返されたファイルをインポートする方法です。

WebViewでファイルを表示する

可能な限り、画像や動画をbase64データURLとして読み込まないでください。ネイティブパスをCapacitorのローカルサーバーが配信するURLに変換します:

import { Capacitor } from '@capacitor/core';

const { uri } = await Filesystem.getUri({ path: 'images/logo.png', directory: Directory.Data });
img.src = Capacitor.convertFileSrc(uri);

iOSでは次のようになります: capacitor://localhost/_capacitor_file_/..., Androidの場合 https://localhost/_capacitor_file_/...。これは次の場合にも使えます: <img>, <video>, <audio>や fetch()、つまりファイルを〜として読み込むこともできます: ArrayBuffer base64なしで:

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

変換後のURLではなくパスを保存してください。変換後の形式は現在のアプリセッションでのみ有効です。

デバイスからファイルを選択

システムピッカーならユーザーが自分で選べ、Android 13以降や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);
}

また、次のものもあります: pickImages, pickVideos, pickMedia と pickDirectory、さらに convertHeicToJpeg iOSの場合。iOSでは、 types 拡張子ではなくMIMEタイプのみを受け付けます。

選択したファイルは一時的な場所にあったり、 content:// 一定期間しか読み取れないURIで参照されている場合があります。後でファイルが必要な場合は、すぐに次の方法で自分のディレクトリにコピーしてください: Filesystem.copy.

ファイルをダウンロード

進捗表示あり: @capacitor/file-transfer

Filesystem.downloadFile はFilesystem 8で非推奨になりました。代替機能はレスポンスを直接ディスクにストリームします:

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

バックグラウンドでの動作: @capgo/capacitor-downloader

ユーザーがアプリを離れてもダウンロードを継続でき、一時停止や再開が可能な大容量ファイルには、Capgo downloaderを使用してください。これは DownloadManager Androidとバックグラウンド URLSession 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
});

相対パスは destination Android ではアプリの外部ファイルディレクトリに解決され、 Documents iOS ではディレクトリに解決されます。どちらも次と同じ場所です: Directory.External.

ファイルのアップロード

送信するためだけにファイルを base64 として読み込むのはやめてください。どちらのアップロードオプションも、ネイティブでディスクから読み込みます:

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

アプリがバックグラウンドに移行してもアップロードを継続する必要がある場合(動画、写真の一括アップロードなど)は、 @capgo/capacitor-uploaderを使用してください。これはバックグラウンドで実行されます。 URLSession iOSでは、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 オブジェクトストレージへのPresigned URLは、大規模ファイルにとって最も信頼性の高いパターンです: APIがURLに署名し、デバイスからストレージへ直接アップロードされます。

ファイルの共有・エクスポート

ユーザーがファイルを別のアプリに送信したり、探しやすい場所に保存できるようにするには:

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

Capgoのファイル共有機能は、ファイルを独自のキャッシュフォルダにコピーし、専用の FileProviderを通じて提供するため、 file_paths.xmlを編集する必要はありません。公式の @capacitor/shareでは、Androidはキャッシュフォルダからのみ共有できます。他のフォルダを追加するには android/app/src/main/res/xml/file_paths.xml.

別のアプリでファイルを開く

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

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

iOSではQuick Lookプレビューが開きます。AndroidではMIMEタイプに対応するデフォルトアプリが開くか、選択画面が表示されます。対応するアプリがない場合、呼び出しは拒否されるため、catchして代わりに共有を提案してください。

よく使うファイル操作のレシピ

PDFを生成する:HTMLをレンダリングするには @capgo/capacitor-pdf-generator またはJSでビルドするには pdf-lib、次にbase64出力を書き出すには writeFile。Capgo CLI は スキャンしてPDF化するチュートリアル 全体のフローを解説します。

アップロード前に写真からGPS情報を削除: @capgo/capacitor-file-compressor リサイズ時に全プラットフォームでEXIFメタデータを削除します。

画像のリサイズや変換: 同じコンプレッサーで幅・高さ・品質・出力形式(HEICからJPEGなど)を扱えます。

大量のファイルをバンドル: フォルダをzip化して @capgo/capacitor-zip 数百ものリクエストの代わりに1つのアーカイブをアップロードします。

Web対応

@capacitor/filesystem IndexedDBを使ってWeb上でも動作するため、開発中はブラウザ上で code を実行できます。留意すべき違いとして、バイナリ読み取りは Blob、ファイルはブラウザのプロファイル内にのみ保存され、ストレージのクォータもかなり小さくなります。Webビルドでは次を推奨します URL.createObjectURL(blob) 表示用です。

トラブルシューティング

「File does not exist」:ディレクトリを混在させたか、絶対パスを directory一緒に渡したかです。どちらか一方を使用してください。

破損したバイナリファイル:base64を書き込みました Encoding.UTF8. エンコーディングを削除します。

大きなファイルでアプリがクラッシュする:ブリッジ経由で base64 を使用。チャンク、file-transfer、または fetch(convertFileSrc(uri)).

Android で画像が表示されない:使用した file:// URLを直接指定。次で変換: Capacitor.convertFileSrc.

Failed to find configured root Androidで共有する場合::ファイルが次のパス外にあります: file_paths.xml。Capgo file sharerを使うか、先に次へコピー: Cache してください。

iOSでファイルが消える:ファイルが次の場所にありました: Cache。iOSはストレージ不足時にそこを消去します。

iCloudストレージが原因のApp Storeリジェクト:次の場所にある大容量ダウンロードコンテンツ: Data または Documents。これを以下へ移動してください: LibraryNoCloud.

次のステップ

ファイルの保存場所、リトライルール、命名規則などの大部分のロジックは JavaScript にあり、 Capgo Live Updates でリリース後に調整できます。Android の共有ストレージと権限については、 スコープ付きストレージガイドを続けてお読みください。また、 ファイルピッカーのドキュメント すべてのピッカーオプションに。

Capacitor アプリ向けの Live Updates

Web レイヤーのバグが本番で発生したら、App Store の審査を何日も待たずに Capgo で修正を配信しましょう。ネイティブの変更は通常の審査フローに残したまま、ユーザーはバックグラウンドでアップデートを受け取れます。

最新のブログ記事

Capgoは、真にプロフェッショナルなモバイルアプリを作るために必要な最高のインサイトを提供します。