cordova-plugin-file
このプラグインは、デバイス上にあるファイルへの読み取り/書き込みアクセスを可能にするFile APIを実装します。
このプラグインは、次のいくつかの仕様に基づいています。HTML5 File API http://www.w3.org/TR/FileAPI/
Directories and System拡張機能の最新版: http://www.w3.org/TR/2012/WD-file-system-api-20120417/ ただし、プラグインコードのほとんどは、以前の仕様が最新であったときに記述されました: http://www.w3.org/TR/2011/WD-file-system-api-20110419/
また、FileWriter仕様も実装しています: http://dev.w3.org/2009/dap/file-system/file-writer.html
注 W3C FileSystem仕様はWebブラウザでは非推奨になっていますが、FileSystem APIは、サポートされているプラットフォームリストに記載されているプラットフォームで、ブラウザプラットフォームを除き、このプラグインを使用してCordovaアプリケーションでサポートされています。
プラグインの使用方法のアイデアを得るには、このページの下部にあるサンプルを確認してください。その他の例(ブラウザ中心)については、HTML5 RocksのFileSystemの記事を参照してください。
その他のストレージオプションの概要については、Cordovaのストレージガイドを参照してください。
このプラグインは、グローバルなcordova.file
オブジェクトを定義します。
オブジェクトはグローバルスコープにありますが、deviceready
イベントが発生するまで、アプリケーションでは利用できません。
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(cordova.file);
}
インストール
cordova plugin add cordova-plugin-file
サポートされているプラットフォーム
- Android
- iOS
- OS X
- Windows*
- ブラウザ
* これらのプラットフォームは、FileReader.readAsArrayBuffer
もFileWriter.write(blob)
もサポートしていません。
ファイルの保存場所
v1.2.0以降では、重要なファイルシステムディレクトリへのURLが提供されています。各URLはfile:///path/to/spot/の形式であり、window.resolveLocalFileSystemURL()
を使用してDirectoryEntry
に変換できます。
-
cordova.file.applicationDirectory
- アプリケーションがインストールされている読み取り専用ディレクトリ。(iOS, Android, BlackBerry 10, OSX, windows) -
cordova.file.applicationStorageDirectory
- アプリケーションのサンドボックスのルートディレクトリ。iOSとWindowsではこの場所は読み取り専用です(ただし、特定のサブディレクトリ[iOSの/Documents
やwindowsの/localState
など]は読み取り/書き込み可能です)。含まれるすべてのデータは、アプリに対してプライベートです。(iOS, Android, BlackBerry 10, OSX) -
cordova.file.dataDirectory
- (Androidでは、外部メモリを使用する必要がある場合は、.externalDataDirectory
を使用します)内部メモリを使用して、アプリケーションのサンドボックス内の永続的でプライベートなデータストレージです。iOSでは、このディレクトリはiCloudと同期されません(.syncedDataDirectory
を使用してください)。(iOS, Android, BlackBerry 10, windows) -
cordova.file.cacheDirectory
- キャッシュされたデータファイルや、アプリで簡単に再作成できるファイルのディレクトリ。デバイスのストレージが不足すると、OSがこれらのファイルを削除する可能性があります。それにもかかわらず、アプリは、OSがここにあるファイルを削除することに依存すべきではありません。(iOS, Android, BlackBerry 10, OSX, windows) -
cordova.file.externalApplicationStorageDirectory
- 外部ストレージ上のアプリケーションスペース。(Android)。Quirksを参照してください。 -
cordova.file.externalDataDirectory
- 外部ストレージ上のアプリ固有のデータファイルを保存する場所。(Android)。Quirksを参照してください。 -
cordova.file.externalCacheDirectory
- 外部ストレージ上のアプリケーションキャッシュ。(Android)。Quirksを参照してください。 -
cordova.file.externalRootDirectory
- 外部ストレージ(SDカード)のルート。(Android, BlackBerry 10)。Quirksを参照してください。 -
cordova.file.tempDirectory
- OSが必要に応じてクリアできる一時ディレクトリ。OSがこのディレクトリをクリアすることに依存しないでください。アプリは常に、該当する場合はファイルを削除する必要があります。(iOS, OSX, windows) -
cordova.file.syncedDataDirectory
- 同期する必要があるアプリ固有のファイル(iCloudなど)を保持します。(iOS, windows) -
cordova.file.documentsDirectory
- アプリにプライベートなファイルですが、他のアプリケーション(Officeファイルなど)にとって意味があります。OSXの場合、これはユーザーの~/Documents
ディレクトリであることに注意してください。(iOS, OSX) -
cordova.file.sharedDirectory
- すべてのアプリケーションでグローバルに利用可能なファイル(BlackBerry 10)
ファイルシステムのレイアウト
技術的には実装の詳細ですが、cordova.file.*
プロパティが実際のデバイス上の物理パスにどのようにマッピングされるかを知っておくと非常に役立ちます。
iOSファイルシステムのレイアウト
デバイスパス | cordova.file.* |
iosExtraFileSystems |
r/w? | 永続的? | OSクリア | 同期 | プライベート |
---|---|---|---|---|---|---|---|
/var/mobile/Applications/<UUID>/ |
applicationStorageDirectory | - | r | N/A | N/A | N/A | はい |
appname.app/ |
applicationDirectory | バンドル | r | N/A | N/A | N/A | はい |
www/ |
- | - | r | N/A | N/A | N/A | はい |
Documents/ |
documentsDirectory | ドキュメント | r/w | はい | いいえ | はい | はい |
NoCloud/ |
- | ドキュメント-nosync | r/w | はい | いいえ | いいえ | はい |
Library |
- | ライブラリ | r/w | はい | いいえ | はい? | はい |
NoCloud/ |
dataDirectory | ライブラリ-nosync | r/w | はい | いいえ | いいえ | はい |
Cloud/ |
syncedDataDirectory | - | r/w | はい | いいえ | はい | はい |
Caches/ |
cacheDirectory | キャッシュ | r/w | はい* | はい*** | いいえ | はい |
tmp/ |
tempDirectory | - | r/w | いいえ** | はい*** | いいえ | はい |
* ファイルはアプリの再起動とアップグレード後も保持されますが、このディレクトリはOSが必要なときにいつでもクリアできます。アプリは、削除される可能性のあるコンテンツを再作成できる必要があります。
** ファイルはアプリの再起動後も保持される可能性がありますが、この動作に依存しないでください。ファイルが更新後も保持される保証はありません。OSがこれらのファイルを削除するタイミング(または削除するかどうか)を保証しないため、アプリは該当する場合はこのディレクトリからファイルを削除する必要があります。
*** OSは必要だと感じたらいつでもこのディレクトリの内容をクリアする可能性がありますが、これに依存しないでください。アプリケーションに適したようにこのディレクトリをクリアする必要があります。
Androidファイルシステムのレイアウト
デバイスパス | cordova.file.* |
AndroidExtraFileSystems |
r/w? | 永続的? | OSクリア | プライベート |
---|---|---|---|---|---|---|
file:///android_asset/ |
applicationDirectory | アセット | r | N/A | N/A | はい |
/data/data/<app-id>/ |
applicationStorageDirectory | - | r/w | N/A | N/A | はい |
キャッシュ |
cacheDirectory | キャッシュ | r/w | はい | はい* | はい |
ファイル |
dataDirectory | ファイル | r/w | はい | いいえ | はい |
ドキュメント |
ドキュメント | r/w | はい | いいえ | はい | |
<sdcard>/ |
externalRootDirectory | sdcard | r/w*** | はい | いいえ | いいえ |
Android/data/<app-id>/ |
externalApplicationStorageDirectory | - | r/w | はい | いいえ | いいえ |
キャッシュ |
externalCacheDirectory | キャッシュ-外部 | r/w | はい | いいえ** | いいえ |
ファイル |
externalDataDirectory | ファイル-外部 | r/w | はい | いいえ | いいえ |
* OSはこのディレクトリを定期的にクリアする可能性がありますが、この動作に依存しないでください。アプリケーションに適したように、このディレクトリの内容をクリアします。ユーザーがキャッシュを手動でパージすると、このディレクトリの内容は削除されます。
** OSはこのディレクトリを自動的にクリアしません。コンテンツの管理はあなた自身が行う必要があります。ユーザーがキャッシュを手動でパージした場合、ディレクトリの内容は削除されます。
*** API 30以降、これらのディレクトリは書き込み可能ではなくなりました。
注: 外部ストレージをマウントできない場合、cordova.file.external*
プロパティはnull
になります。
Androidの外部ストレージの癖
スコープ付きストレージの導入により、外部ストレージへのアクセスは、File APIを介して信頼性が低くなったり、制限されたりしています。スコープ付きストレージは、API 29で導入されました。既存のアプリはオプトアウトする機能がある場合がありますが、このオプションは新しいアプリでは利用できません。Android API 30以降では、スコープ付きストレージが完全に適用されます。
さらに、API 29では、ダイレクトファイルアクセスはサポートされていません。つまり、このプラグインは、API 29デバイスの外部ストレージメディアにアクセスできません。
API 30では、FUSEが導入され、File APIを使用して外部ストレージへのアクセスが制限され、このプラグインが再び部分的に機能するようになりました。
制限されたアクセスには、以下が含まれますが、これに限定されません。
- 適切な
READ_EXTERNAL
またはREAD_MEDIA_*パーミッションによる読み取り専用アクセス。 - 読み取り専用アクセスは、メディアファイルに制限されていますが、ドキュメントには制限されていません。
- 書き込みは、アプリが所有するファイルのみに制限されています。サードパーティ製アプリが所有するファイル(たとえば、カメラプラグインを使用して作成された画像ファイルなど)を変更することは、File APIではできません。
- 外部ストレージ内のすべてのパスが書き込み可能であるとは限りません。
これらの制限は、外部ファイルシステム(例: cordova.file.external*
パス)にのみ適用されます。cordova.file.dataDirectory
パスなどの内部ファイルシステムには、これらの制限は課されません。
外部ファイルシステムとのインターフェースがアプリケーションの要件である場合は、代わりにMediaStoreプラグインを使用することを検討してください。
OS Xファイルシステムのレイアウト
デバイスパス | cordova.file.* |
iosExtraFileSystems |
r/w? | OSクリア | プライベート |
---|---|---|---|---|---|
/Applications/<appname>.app/ |
- | バンドル | r | N/A | はい |
Content/Resources/ |
applicationDirectory | - | r | N/A | はい |
~/Library/Application Support/<bundle-id>/ |
applicationStorageDirectory | - | r/w | いいえ | はい |
ファイル/ |
dataDirectory | - | r/w | いいえ | はい |
~/Documents/ |
documentsDirectory | ドキュメント | r/w | いいえ | いいえ |
~/Library/Caches/<bundle-id>/ |
cacheDirectory | キャッシュ | r/w | いいえ | はい |
/tmp/ |
tempDirectory | - | r/w | はい* | はい |
/ |
rootDirectory | ルート | r/w | いいえ** | いいえ |
注: これはサンドボックス化されていないアプリケーションのレイアウトです。サンドボックスを有効にすると、applicationStorageDirectory
は` ~/Library/Containers/の下になります。
※ ファイルはアプリの再起動やアップグレード後も保持されますが、このディレクトリはOSが必要に応じてクリアすることがあります。アプリは削除される可能性のあるコンテンツを再作成できるようにする必要があります。また、アプリケーションに適したタイミングでこのディレクトリをクリアする必要があります。
※※ ファイルシステム全体へのアクセスを許可します。これはサンドボックス化されていないアプリでのみ利用可能です。
Windowsファイルシステムレイアウト
デバイスパス | cordova.file.* |
r/w? | 永続的? | OSクリア | プライベート |
---|---|---|---|---|---|
ms-appdata:/// |
applicationDirectory | r | N/A | N/A | はい |
local/ |
dataDirectory | r/w | はい | いいえ | はい |
temp/ |
cacheDirectory | r/w | いいえ | はい* | はい |
temp/ |
tempDirectory | r/w | いいえ | はい* | はい |
roaming/ |
syncedDataDirectory | r/w | はい | いいえ | はい |
※ OSはこのディレクトリを定期的にクリアする可能性があります。
Androidの特異性
Androidの永続ストレージの場所
Androidデバイスに永続ファイルを保存するための有効な場所は複数あります。さまざまな可能性の詳細については、こちらのページをご覧ください。
以前のバージョンのプラグインでは、SDカード(または同等のストレージパーティション)がマウントされているかどうかをデバイスが主張するかに基づいて、起動時に一時ファイルと永続ファイルの場所を選択していました。SDカードがマウントされている場合、または(Nexusデバイスのように)大きな内部ストレージパーティションが利用可能な場合、永続ファイルはその領域のルートに保存されていました。これは、すべてのCordovaアプリがカード上で利用可能なすべてのファイルを見ることができたことを意味します。
SDカードが利用できない場合、以前のバージョンでは/data/data/<packageId>
の下にデータを保存していました。これにより、アプリは互いに分離されますが、ユーザー間でデータが共有される可能性は残っていました。
アプリケーションのconfig.xml
ファイルで設定することにより、内部ファイルストレージの場所、または以前のロジックを使用してファイルを保存するかどうかを選択できるようになりました。これを行うには、次のいずれかの行をconfig.xml
に追加します。
<preference name="AndroidPersistentFileLocation" value="Internal" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
この行がない場合、FileプラグインはデフォルトでInternal
を使用します。設定タグが存在し、これらの値のいずれでもない場合、アプリケーションは起動しません。
以前にこのプラグインの古い(3.0.0より前の)バージョンを使用してユーザーにアプリケーションを配布し、永続ファイルシステムにファイルを保存した場合、config.xml
が永続ファイルシステムの場所を指定していない場合は、設定をCompatibility
に設定する必要があります。「Internal」に場所を切り替えると、アプリケーションをアップグレードした既存のユーザーが、デバイスによっては以前に保存したファイルにアクセスできなくなる可能性があることを意味します。
アプリケーションが新しい場合、または以前に永続ファイルシステムにファイルを保存したことがない場合は、一般的にInternal
設定が推奨されます。
/android_assetに対する遅い再帰的な操作
Androidでは、アセットディレクトリのリスト表示は非常に遅いです。ただし、Androidプロジェクトのルートにsrc/android/build-extras.gradle
を追加することで高速化できます(cordova-android@4.0.0以上も必要です)。
Marshmallowで外部ストレージがマウントされていない場合の書き込み権限
Marshmallowでは、外部の場所に読み書きするときにアプリに権限を要求する必要があります。デフォルトでは、アプリはcordova.file.applicationStorageDirectory
およびcordova.file.externalApplicationStorageDirectory
への書き込み権限を持っており、外部ストレージがマウントされていない場合を除き、プラグインはこれらの2つのディレクトリに対する権限を要求しません。ただし、制限により、外部ストレージがマウントされていない場合、cordova.file.externalApplicationStorageDirectory
への書き込み権限を要求することになります。
SDKターゲットが29未満の場合
公式のAndroid 11のストレージアップデートドキュメントによると、WRITE_EXTERNAL_STORAGE
権限はもはや機能せず、アクセスを提供しません。
Build.VERSION_CODES.Q
(SDK 29)より前のAPIレベルをターゲットとするアプリでこの権限が許可リストに登録されていない場合、この権限をアプリに付与することはできません。
この権限を追加する必要がある場合は、次の内容をconfig.xml
に追加してください。
<config-file target="AndroidManifest.xml" parent="/*" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
</config-file>
iOSの特異性
cordova.file.applicationStorageDirectory
は読み取り専用です。ルートディレクトリ内にファイルを保存しようとすると失敗します。iOS用に定義された他のcordova.file.*
プロパティのいずれかを使用してください(applicationDirectory
とapplicationStorageDirectory
のみが読み取り専用です)。FileReader.readAsText(blob, encoding)
encoding
パラメータはサポートされておらず、常にUTF-8エンコーディングが有効です。
iOSの永続ストレージの場所
iOSデバイスに永続ファイルを保存するための有効な場所は2つあります。DocumentsディレクトリとLibraryディレクトリです。以前のバージョンのプラグインでは、永続ファイルは常にDocumentsディレクトリにのみ保存されていました。これにより、アプリケーションのすべてのファイルがiTunesで表示されるという副作用があり、特にエクスポート用の完全なドキュメントを作成するのではなく、多数の小さなファイルを処理するアプリケーションでは、意図しないことがよくありました。これは、このディレクトリの意図された目的です。
アプリケーションのconfig.xml
ファイルで設定することにより、ファイルをDocumentsディレクトリまたはLibraryディレクトリに保存するかどうかを選択できるようになりました。これを行うには、次のいずれかの行をconfig.xml
に追加します。
<preference name="iosPersistentFileLocation" value="Library" />
<preference name="iosPersistentFileLocation" value="Compatibility" />
この行がない場合、FileプラグインはデフォルトでCompatibility
を使用します。設定タグが存在し、これらの値のいずれでもない場合、アプリケーションは起動しません。
以前にこのプラグインの古い(1.0より前の)バージョンを使用してユーザーにアプリケーションを配布し、永続ファイルシステムにファイルを保存した場合、設定をCompatibility
に設定する必要があります。場所をLibrary
に切り替えると、アプリケーションをアップグレードした既存のユーザーが、以前に保存したファイルにアクセスできなくなることを意味します。
アプリケーションが新しい場合、または以前に永続ファイルシステムにファイルを保存したことがない場合は、一般的にLibrary
設定が推奨されます。
ブラウザの特異性
一般的な特異性と注意点
- 各ブラウザは、独自のサンドボックス化されたファイルシステムを使用します。IEとFirefoxは、基盤としてIndexedDBを使用します。すべてのブラウザは、パス内のディレクトリ区切り文字としてスラッシュを使用します。
- ディレクトリエントリは連続して作成する必要があります。たとえば、
fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback)
という呼び出しは、dir1が存在しない場合に失敗します。 - プラグインは、アプリケーションの初回起動時に永続ストレージを使用するためのユーザー許可を要求します。
- プラグインは
cdvfile://127.0.0.1
(ローカルリソース)のみをサポートします。つまり、外部リソースはcdvfile
経由ではサポートされていません。 - プラグインは、「ファイルシステムAPI 8.3命名規則」に従いません。
- BlobとFileの
close
関数はサポートされていません。 FileSaver
とBlobBuilder
は、このプラグインではサポートされておらず、スタブもありません。- プラグインは
requestAllFileSystems
をサポートしていません。この関数は仕様にも欠落しています。 - 既存のディレクトリに対して
create: true
フラグを使用した場合、ディレクトリ内のエントリは削除されません。 - コンストラクタを介して作成されたファイルはサポートされていません。代わりにentry.fileメソッドを使用する必要があります。
- 各ブラウザは、blob URL参照に独自の形式を使用します。
readAsDataURL
関数はサポートされていますが、Chromeのメディアタイプはエントリ名拡張子に依存し、IEのメディアタイプは常に空(これは仕様によるとtext-plain
と同じです)、Firefoxのメディアタイプは常にapplication/octet-stream
です。たとえば、コンテンツがabcdefg
の場合、Firefoxはdata:application/octet-stream;base64,YWJjZGVmZw==
を返し、IEはdata:;base64,YWJjZGVmZw==
を返し、Chromeはdata:<エントリ名の拡張子によって異なるメディアタイプ>;base64,YWJjZGVmZw==
を返します。toInternalURL
は、file:///persistent/path/to/entry
という形式でパスを返します(Firefox、IE)。Chromeは、cdvfile://127.0.0.1/persistent/file
という形式でパスを返します。
Chromeの特異性
- Chromeファイルシステムは、デバイスの準備完了イベントの直後には準備ができていません。回避策として、
filePluginIsReady
イベントをサブスクライブできます。例window.addEventListener('filePluginIsReady', function(){ console.log('File plugin is ready');}, false);
window.isFilePluginReadyRaised
関数を使用して、イベントがすでに発生したかどうかを確認できます。 - window.requestFileSystem TEMPORARYおよびPERSISTENTファイルシステムのクォータはChromeでは制限されていません。
- Chromeで永続ストレージを増やすには、
window.initPersistentFileSystem
メソッドを呼び出す必要があります。永続ストレージのクォータはデフォルトで5MBです。 - Chromeは、
file:///
プロトコル経由でAPIをサポートするために--allow-file-access-from-files
実行引数を必要とします。 - 既存の
Entry
を取得するときにフラグ{create:true}
を使用すると、File
オブジェクトは変更されません。 - Chromeでは、イベントの
cancelable
プロパティがtrueに設定されます。これは仕様に反します。 - Chromeの
toURL
関数は、アプリケーションホストに応じてfilesystem:
プレフィックス付きのパスを返します。たとえば、filesystem:file:///persistent/somefile.txt
、filesystem:https://127.0.0.1:8080/persistent/somefile.txt
などです。 toURL
関数の結果は、ディレクトリエントリの場合、末尾にスラッシュを含みません。ただし、Chromeはスラッシュ付きのURLでディレクトリを正しく解決します。resolveLocalFileSystemURL
メソッドでは、インバウンドurl
にfilesystem
プレフィックスが必要です。たとえば、resolveLocalFileSystemURL
のurl
パラメーターは、Androidのfile:///persistent/somefile.txt
という形式ではなく、filesystem:file:///persistent/somefile.txt
という形式である必要があります。- 非推奨の
toNativeURL
関数はサポートされておらず、スタブもありません。 setMetadata
関数は仕様に記述されておらず、サポートされていません。- 存在しないファイルシステムを要求すると、SYNTAX_ERR(コード:8)の代わりにINVALID_MODIFICATION_ERR(コード:9)がスローされます。
- すでに存在するファイルまたはディレクトリを排他的に作成しようとすると、PATH_EXISTS_ERR(コード:12)の代わりにINVALID_MODIFICATION_ERR(コード:9)がスローされます。
- ルートファイルシステムでremoveRecursivelyを呼び出そうとすると、NO_MODIFICATION_ALLOWED_ERR(コード:6)の代わりにINVALID_MODIFICATION_ERR(コード:9)がスローされます。
- 存在しないディレクトリにmoveToしようとすると、NOT_FOUND_ERR(コード:1)の代わりにINVALID_MODIFICATION_ERR(コード:9)がスローされます。
IndexedDBベースの実装の特異性(FirefoxとIE)
.
と..
はサポートされていません。- IEは
file:///
モードをサポートしていません。ホストモード(https://127.0.0.1:xxxx)のみがサポートされています。 - Firefoxのファイルシステムサイズは制限されていませんが、50MB拡張ごとにユーザー許可が要求されます。IE10では、プロンプトなしでファイルシステムのインプリメンテーションで使用されるAppCacheとIndexedDBを合計10MBまで許可します。そのレベルに達すると、サイトごとに最大250MBまで増やすことを許可するかどうかを尋ねられます。したがって、
requestFileSystem
関数のsize
パラメーターは、FirefoxとIEのファイルシステムには影響しません。 readAsBinaryString
関数はSpecsに記載されておらず、IEではサポートされておらず、スタブもありません。file.type
は常にnullです。- 削除されたDirectoryEntryインスタンスのコールバック結果を使用してエントリを作成しないでください。そうしないと、「ハングエントリ」が発生します。
- 書き込んだばかりのファイルを読み取る前に、このファイルの新しいインスタンスを取得する必要があります。
- Spec に記載されていない
setMetadata
関数は、modificationTime
フィールドの変更のみをサポートします。 copyTo
関数とmoveTo
関数は、ディレクトリをサポートしません。- ディレクトリのメタデータはサポートされていません。
- Entry.remove と directoryEntry.removeRecursively は、空でないディレクトリを削除する際に失敗しません。削除されるディレクトリは、その内容とともにクリーンアップされます。
abort
関数とtruncate
関数はサポートされていません。- 進捗イベントは発生しません。たとえば、このハンドラーは実行されません。
writer.onprogress = function() { /*commands*/ };
アップグレードに関する注意点
このプラグインの v1.0.0 では、公開されている仕様に合わせて、FileEntry
および DirectoryEntry
の構造が変更されました。
以前の(1.0.0 より前の)バージョンのプラグインでは、デバイスの絶対ファイルロケーションが Entry
オブジェクトの fullPath
プロパティに格納されていました。これらのパスは通常、次のような形式でした。
/var/mobile/Applications/<application UUID>/Documents/path/to/file (iOS)
/storage/emulated/0/path/to/file (Android)
これらのパスは、Entry
オブジェクトの toURL()
メソッドによっても返されていました。
v1.0.0 では、fullPath
属性は、HTML ファイルシステムのルートに対する相対パスであるファイルのパスです。したがって、上記のパスは両方とも、fullPath
が次の FileEntry
オブジェクトで表されるようになりました。
/path/to/file
アプリケーションがデバイスの絶対パスを使用しており、以前に Entry
オブジェクトの fullPath
プロパティを通じてそれらのパスを取得していた場合は、entry.toURL()
を使用するようにコードを更新する必要があります。
下位互換性のために、resolveLocalFileSystemURL()
メソッドはデバイスの絶対パスを受け入れ、そのファイルが TEMPORARY
または PERSISTENT
ファイルシステムのいずれかに存在する場合は、それに対応する Entry
オブジェクトを返します。
これは特に、デバイスの絶対パスを以前使用していた(そして今でも受け入れることができる)File-Transfer プラグインで問題になっていました。FileSystem URL で正しく動作するように更新されたため、entry.fullPath
を entry.toURL()
に置き換えることで、そのプラグインをデバイス上のファイルで動作させる際の問題が解決されるはずです。
v1.1.0 では、可能な限り絶対 'file://' URL を返すように toURL()
の戻り値が変更されました ( CB-6394 を参照)。'cdvfile:'-URL を確実にするには、toInternalURL()
を使用できます。このメソッドは、次のような形式のファイルシステム URL を返すようになりました。
cdvfile://127.0.0.1/persistent/path/to/file
これは、ファイルを一意に識別するために使用できます。
v7.0.0 では、アプリのコンテンツが file://
スキームから提供される場合、Android の toURL()
の戻り値が絶対 file://
URL を返すように更新されました。
アプリのコンテンツが http(s)://
スキームから提供される場合は、代わりに cdvfile
形式の URL が返されます。cdvfile
形式の URL は、内部メソッド toInternalURL()
から作成されます。
toInternalURL()
が返すファイルシステム URL の例
https://127.0.0.1/persistent/path/to/file
正しい URL が返されるように、常に toURL()
を使用することを推奨します。
cdvfile プロトコル
- Android ではサポートされていません
目的
cdvfile://127.0.0.1/persistent|temporary|another-fs-root*/path/to/file
は、プラットフォームに依存しないファイルパスに使用できます。cdvfile パスは、コアプラグインでサポートされています。たとえば、cordova-plugin-file-transfer
を介して mp3 ファイルを cdvfile パスにダウンロードし、cordova-plugin-media
を介して再生できます。
*注: 利用可能な fs ルートの詳細については、ファイルの保存場所、ファイルシステムのレイアウト、およびプラグインの設定を参照してください。
cdvfile
をタグの src
として使用するには、resolveLocalFileSystemURL
を介して取得できる解決済みの fileEntry の toURL()
メソッドを介してネイティブパスに変換できます。以下の例を参照してください。
cdvfile://
パスを DOM で直接使用することもできます。たとえば、
<img src="cdvfile://127.0.0.1/persistent/img/logo.png" />
注: このメソッドでは、次のコンテンツセキュリティルールを更新する必要があります。
- インデックスページの
Content-Security-Policy
メタタグにcdvfile:
スキームを追加します。例:<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:
cdvfile:https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
config.xml
に<access origin="cdvfile://*" />
を追加します。
cdvfile:// をネイティブパスに変換する
resolveLocalFileSystemURL('cdvfile://127.0.0.1/temporary/path/to/file.mp4', function(entry) {
var nativePath = entry.toURL();
console.log('Native URI: ' + nativePath);
document.getElementById('video').src = nativePath;
ネイティブパスを cdvfile:// に変換する
resolveLocalFileSystemURL(nativePath, function(entry) {
console.log('cdvfile URI: ' + entry.toInternalURL());
コアプラグインで cdvfile を使用する
fileTransfer.download(uri, 'cdvfile://127.0.0.1/temporary/path/to/file.mp3', function (entry) { ...
var my_media = new Media('cdvfile://127.0.0.1/temporary/path/to/file.mp3', ...);
my_media.play();
cdvfile の癖
- DOM で
cdvfile://
パスを使用することは、Windows プラットフォームではサポートされていません (代わりにパスをネイティブに変換できます)。
エラーコードと意味の一覧
エラーがスローされると、次のいずれかのコードが使用されます。
コード | 定数 |
---|---|
1 | NOT_FOUND_ERR |
2 | SECURITY_ERR |
3 | ABORT_ERR |
4 | NOT_READABLE_ERR |
5 | ENCODING_ERR |
6 | NO_MODIFICATION_ALLOWED_ERR |
7 | INVALID_STATE_ERR |
8 | SYNTAX_ERR |
9 | INVALID_MODIFICATION_ERR |
10 | QUOTA_EXCEEDED_ERR |
11 | TYPE_MISMATCH_ERR |
12 | PATH_EXISTS_ERR |
プラグインの設定 (オプション)
利用可能なファイルシステムのセットは、プラットフォームごとに設定できます。iOS と Android の両方が、config.xml
の
<preference name="iosExtraFilesystems" value="library,library-nosync,documents,documents-nosync,cache,bundle,root" />
<preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" />
Android
files
: アプリケーションの内部ファイルストレージディレクトリfiles-external
: アプリケーションの外部ファイルストレージディレクトリsdcard
: グローバル外部ファイルストレージディレクトリ (SD カードがインストールされている場合は SD カードのルート)。これを使用するには、android.permission.WRITE_EXTERNAL_STORAGE
権限が必要です。cache
: アプリケーションの内部キャッシュディレクトリcache-external
: アプリケーションの外部キャッシュディレクトリassets
: アプリケーションのバンドル (読み取り専用)root
: デバイスファイルシステム全体applicationDirectory
: 制限付きアクセスの読み取り専用。このディレクトリ内のファイルのコピーは可能ですが、直接読み取ると「ファイルが見つかりません」になります。Android は、"files" ファイルシステム内の "/Documents/" サブディレクトリを表す "documents" という名前の特別なファイルシステムもサポートしています。
iOS
library
: アプリケーションのライブラリディレクトリdocuments
: アプリケーションのドキュメントディレクトリcache
: アプリケーションのキャッシュディレクトリbundle
: アプリケーションのバンドル。ディスク上のアプリ自体の場所 (読み取り専用)root
: デバイスファイルシステム全体
デフォルトでは、ライブラリとドキュメントディレクトリは iCloud に同期できます。library-nosync
と documents-nosync
という 2 つの追加のファイルシステムをリクエストすることもできます。これらは、/Library
または /Documents
ファイルシステム内の同期されていない特別なディレクトリを表します。
サンプル: ファイルとディレクトリの作成、ファイルの書き込み、読み込み、および追加
File プラグインを使用すると、アプリの一時的または永続的なストレージ場所 (サンドボックス化されたストレージ) にファイルを保存したり、その他のプラットフォームに依存する場所にファイルを保存したりできます。このセクションのコードスニペットは、次の異なるタスクを示しています。
- ファイルシステムへのアクセス
- ファイルを保存するためのクロスプラットフォームの Cordova ファイル URL の使用 (詳細については、ファイルの保存場所を参照してください)
- ファイルとディレクトリの作成
- ファイルへの書き込み
- ファイルの読み込み
- ファイルへの追加
- 画像ファイルの表示
永続的なファイルの作成
File プラグイン API を使用する前に、requestFileSystem
を使用してファイルシステムにアクセスできます。この際、永続的なストレージまたは一時的なストレージをリクエストできます。永続的なストレージは、ユーザーによって許可されない限り削除されません。
requestFileSystem
を使用してファイルシステムへのアクセスを取得すると、サンドボックス化されたファイルシステムに対してのみアクセスが許可されます (サンドボックスはアプリ自体へのアクセスを制限します)。デバイス上の任意のファイルシステムロケーションへの一般的なアクセスは許可されません。(サンドボックス化されたストレージの外部にあるファイルシステムロケーションにアクセスするには、プラットフォーム固有のロケーションをサポートする window.resolveLocalFileSystemURL などの他のメソッドを使用してください。この一例については、ファイルの追加を参照してください)。
永続的なストレージのリクエストを以下に示します。
注 WebView クライアント (ブラウザの代わりに) またはネイティブアプリ (Windows) をターゲットとする場合、永続的なストレージを使用する前に
requestQuota
を使用する必要はありません。
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile("newPersistentFile.txt", { create: true, exclusive: false }, function (fileEntry) {
console.log("fileEntry is file?" + fileEntry.isFile.toString());
// fileEntry.name == 'someFile.txt'
// fileEntry.fullPath == '/someFile.txt'
writeFile(fileEntry, null);
}, onErrorCreateFile);
}, onErrorLoadFs);
成功コールバックは、FileSystem オブジェクト (fs) を受け取ります。fs.root
を使用して、ファイルを作成または取得するために使用できる DirectoryEntry オブジェクトを返します (getFile
を呼び出すことによって)。この例では、fs.root
は、サンドボックス化されたファイルシステムの永続的なストレージを表す DirectoryEntry オブジェクトです。
getFile
の成功コールバックは、FileEntry オブジェクトを受け取ります。これを使用して、ファイルの書き込みおよび読み取り操作を実行できます。
一時ファイルの作成
以下は、一時的なストレージのリクエストの例です。一時的なストレージは、デバイスのメモリが不足した場合にオペレーティングシステムによって削除される場合があります。
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
console.log('file system open: ' + fs.name);
createFile(fs.root, "newTempFile.txt", false);
}, onErrorLoadFs);
一時的なストレージを使用している場合は、getFile
を呼び出すことによってファイルを作成または取得できます。永続的なストレージの例と同様に、これにより、読み取りまたは書き込み操作に使用できる FileEntry オブジェクトが提供されます。
function createFile(dirEntry, fileName, isAppend) {
// Creates a new file or returns the file if it already exists.
dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {
writeFile(fileEntry, null, isAppend);
}, onErrorCreateFile);
}
ファイルへの書き込み
FileEntry オブジェクトを取得したら、createWriter
を呼び出すことでファイルに書き込むことができます。これは、成功コールバックで FileWriter オブジェクトを返します。FileWriter の write
メソッドを呼び出してファイルに書き込みます。
function writeFile(fileEntry, dataObj) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file write...");
readFile(fileEntry);
};
fileWriter.onerror = function (e) {
console.log("Failed file write: " + e.toString());
};
// If data object is not passed in,
// create a new Blob instead.
if (!dataObj) {
dataObj = new Blob(['some file data'], { type: 'text/plain' });
}
fileWriter.write(dataObj);
});
}
ファイルの読み込み
既存のファイルを読み取るには、FileEntry オブジェクトも必要です。FileEntry の file プロパティを使用してファイル参照を取得し、新しい FileReader オブジェクトを作成します。readAsText
などのメソッドを使用して、読み取り操作を開始できます。読み取り操作が完了すると、this.result
に読み取り操作の結果が格納されます。
function readFile(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
console.log("Successful file read: " + this.result);
displayFileData(fileEntry.fullPath + ": " + this.result);
};
reader.readAsText(file);
}, onErrorReadFile);
}
別のメソッドを使用したファイルの追加
もちろん、多くの場合、新しいファイルを作成するのではなく、既存のファイルに追加することが必要になります。以下はその例です。この例では、window.resolveLocalFileSystemURL を使用してファイルシステムにアクセスする別の方法を示します。この例では、クロスプラットフォームの Cordova ファイル URL である cordova.file.dataDirectory を関数に渡します。成功コールバックは DirectoryEntry オブジェクトを受け取ります。これは、ファイルの作成などのために使用できます。
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
console.log('file system open: ' + dirEntry.name);
var isAppend = true;
createFile(dirEntry, "fileToAppend.txt", isAppend);
}, onErrorLoadFs);
この使用法に加えて、resolveLocalFileSystemURL
を使用して、サンドボックス化されたストレージシステムの一部ではないファイルシステムロケーションにアクセスできます。詳細については、ファイルの保存場所を参照してください。これらのストレージロケーションの多くはプラットフォーム固有です。cdvfile プロトコルを使用して、クロスプラットフォームのファイルシステムロケーションを resolveLocalFileSystemURL
に渡すこともできます。
追加操作の場合、前のコードで呼び出される createFile
関数には新しいものはありません (実際のコードについては、前の例を参照してください)。createFile
は writeFile
を呼び出します。writeFile
では、追加操作がリクエストされているかどうかを確認します。
FileWriter オブジェクトを取得したら、seek
メソッドを呼び出し、書き込みを行う位置のインデックス値を渡します。この例では、ファイルが存在するかどうかもテストします。seek を呼び出した後、FileWriter の write メソッドを呼び出します。
function writeFile(fileEntry, dataObj, isAppend) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file read...");
readFile(fileEntry);
};
fileWriter.onerror = function (e) {
console.log("Failed file read: " + e.toString());
};
// If we are appending data to file, go to the end of the file.
if (isAppend) {
try {
fileWriter.seek(fileWriter.length);
}
catch (e) {
console.log("file doesn't exist!");
}
}
fileWriter.write(dataObj);
});
}
既存のバイナリファイルの保存
サンドボックス化されたファイルシステムで作成したばかりのファイルに書き込む方法をすでに示しました。既存のファイルにアクセスして、それをデバイスに保存できるものに変換する必要がある場合はどうすればよいでしょうか? この例では、xhr リクエストを使用してファイルを取得し、サンドボックス化されたファイルシステムのキャッシュに保存します。
ファイルを取得する前に、requestFileSystem
を使用して FileSystem 参照を取得します。メソッド呼び出しで window.TEMPORARY を渡すことによって (以前と同じ)、返される FileSystem オブジェクト (fs) は、サンドボックス化されたファイルシステムのキャッシュを表します。fs.root
を使用して、必要な DirectoryEntry オブジェクトを取得します。
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
console.log('file system open: ' + fs.name);
getSampleFile(fs.root);
}, onErrorLoadFs);
完全を期すために、Blobイメージを取得するxhrリクエストを以下に示します。このコードには、すでに取得済みのDirectoryEntry参照をsaveFile関数への引数として渡すことを除いて、Cordova固有のものは何もありません。Blobイメージを保存し、後でファイル(操作を検証するため)を読み取った後に表示します。
function getSampleFile(dirEntry) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://cordova.dokyumento.jp/static/img/cordova_bot.png', true);
xhr.responseType = 'blob';
xhr.onload = function() {
if (this.status == 200) {
var blob = new Blob([this.response], { type: 'image/png' });
saveFile(dirEntry, blob, "downloadedImage.png");
}
};
xhr.send();
}
注 Cordova 5のセキュリティのため、上記のコードでは、index.htmlのContent-Security-Policy要素にドメイン名https://cordova.dokyumento.jpを追加する必要があります。index.htmlの要素に追加する必要があります。
ファイルを取得した後、内容を新しいファイルにコピーします。現在のDirectoryEntryオブジェクトは、すでにアプリキャッシュに関連付けられています。
function saveFile(dirEntry, fileData, fileName) {
dirEntry.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
writeFile(fileEntry, fileData);
}, onErrorCreateFile);
}
writeFileでは、BlobオブジェクトをdataObjとして渡すと、新しいファイルに保存されます。
function writeFile(fileEntry, dataObj, isAppend) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file write...");
if (dataObj.type == "image/png") {
readBinaryFile(fileEntry);
}
else {
readFile(fileEntry);
}
};
fileWriter.onerror = function(e) {
console.log("Failed file write: " + e.toString());
};
fileWriter.write(dataObj);
});
}
ファイルへの書き込み後、それを読み取り表示します。イメージはバイナリデータとして保存されているため、FileReader.readAsArrayBufferを使用して読み取ることができます。
function readBinaryFile(fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function() {
console.log("Successful file write: " + this.result);
displayFileData(fileEntry.fullPath + ": " + this.result);
var blob = new Blob([new Uint8Array(this.result)], { type: "image/png" });
displayImage(blob);
};
reader.readAsArrayBuffer(file);
}, onErrorReadFile);
}
データを読み取った後、次のようなコードを使用してイメージを表示できます。window.URL.createObjectURLを使用して、BlobイメージのDOM文字列を取得します。
function displayImage(blob) {
// Displays image if result is a valid DOM string for an image.
var elem = document.getElementById('imageFile');
// Note: Use window.URL.revokeObjectURL when finished with image.
elem.src = window.URL.createObjectURL(blob);
}
イメージファイルの表示
FileEntryを使用してイメージを表示するには、toURL
メソッドを呼び出すことができます。
function displayImageByFileURL(fileEntry) {
var elem = document.getElementById('imageFile');
elem.src = fileEntry.toURL();
}
FileEntryの代わりにプラットフォーム固有のURIを使用しており、イメージを表示したい場合は、index.htmlのContent-Security-Policy要素にURIのメイン部分を含める必要がある場合があります。index.htmlの要素に含める必要があります。たとえば、Windows 10では、ms-appdata:
を要素に含めることができます。以下に例を示します。
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: ms-appdata: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
ディレクトリの作成
ここに示すコードでは、アプリのストレージ場所のルートにディレクトリを作成します。このコードは、書き込み可能なストレージ場所(つまり、任意のDirectoryEntry)で使用できます。ここでは、この関数にfs.rootを渡すことで、アプリケーションキャッシュに書き込みます(FileSystemオブジェクトを取得するためにwindow.TEMPORARYを使用したと仮定します)。
このコードは、アプリケーションキャッシュに/NewDirInRoot/imagesフォルダーを作成します。プラットフォーム固有の値については、「ファイルシステムレイアウト」を参照してください。
function createDirectory(rootDirEntry) {
rootDirEntry.getDirectory('NewDirInRoot', { create: true }, function (dirEntry) {
dirEntry.getDirectory('images', { create: true }, function (subDirEntry) {
createFile(subDirEntry, "fileInNewSubDir.txt");
}, onErrorGetDir);
}, onErrorGetDir);
}
サブフォルダーを作成する場合は、上記のコードに示すように、各フォルダーを個別に作成する必要があります。