前回は、実際にFile APIを使ってファイルの操作を行う準備について説明しました。今回は前回に続いて以下の操作について紹介します。
- TEMPORARYファイルシステムのファイル一覧を取得し、画面に表示
- Camera APIで作成したファイルをPERSISTENTファイルシステムに移動
- PERSISTENTファイルシステムに、画像ファイルの詳細データを格納したテキストファイルを作成
今回も前回と同様、iOSとAndroid、両OSでの手順を紹介していきます。実機を使用せず、Mac OS上のiOSシミュレータ、Windows上のAndroidエミュレータとPCに接続されているカメラデバイスを用いた手順を紹介します。
TEMPORARYファイルシステムのファイル一覧を取得(iOS/Android)
前回紹介したFile APIのオブジェクト、メソッドを用いて、TEMPORARYファイルシステム上のファイル一覧を取得してみましょう。ソースコードは次のとおりです。
このサンプルコードでは、TEMPORARYファイルシステムのファイル一覧を取得し、列挙します。iOSシミュレータ、Androidエミュレータで実行した場合の動作結果は次のとおりです。
リスト1サンプルコードで行っている処理の流れは次のとおりです。
- requestFileSystemでTEMPORARYファイルシステムを取得
- FileSystemオブジェクトのrootプロパティから、TEMPORARYファイルシステムのルートディレクトリの情報(DirectoryEntryオブジェクト)を取得
- DirectoryEntryオブジェクトのcreateReaderメソッドを用いて、DirectoryReaderオブジェクトを作成
- DirectoryReaderオブジェクトのreadEntriesメソッドを用いて、ディレクトリ内のファイル/ディレクトリエントリを読み込む
- readEntriesメソッドから渡されたFileEntry/DirectoryEntryの配列を受け取り、ファイル名を<li>要素で列挙
第4回の記事を参照し、各オブジェクトの関係性や処理の流れを把握しておくと理解しやすいでしょう。
18行目のrequestFileSystemメソッドは、PERSISTENTまたはTEMPORARYのどちらかのFileSystemオブジェクトを取得します。第3引数で指定したgetFilesFromDirectory関数に、取得したFileSystemオブジェクトが渡されます。
FileSystemオブジェクトのrootプロパティには、DirectoryEntryオブジェクトが格納されています。DirectoryEntryオブジェクトのcreateReaderメソッドを用いて、TEMPORARYファイルシステム、ルートディレクトリ内のディレクトリ・ファイルを読み込むためのオブジェクト--DirectoryReaderオブジェクトを作成し、directoryReader変数に格納します。
DirectoryReaderオブジェクトには1つだけメソッドが用意されています。ディレクトリ内のエントリを読み込むメソッド--readEntriesメソッドを用いて、ディレクトリ内のディレクトリ・ファイル情報を第1引数で指定したputFileName関数に渡します。
あるディレクトリ内にディレクトリが1つ、ファイルが3つある場合には、次のような配列がコールバック関数に渡されます。
putFileName関数はDirectoryEntry/FileEntryが格納された配列を受け取り、for文で配列の要素の数だけDOMを作成して、ディレクトリ名/ファイル名を列挙します。
fail関数はFile APIでファイルを操作している場合にエラーが起こった際に呼び出される関数です。FileErrorオブジェクトを受け取り、エラーコードを表示します。数値とエラーコードの対応は次のとおりです。
Camera APIで作成したファイルをPERSISTENTファイルシステムに移動(iOS/Android)
Camera APIで作成されるファイルを、PERSISTENTファイルシステムに移動してみましょう。Camera APIからファイルパスが渡されるので、resolveLocalFileSystemURIメソッドを用いるのが便利です。
ソースコードは次のとおりです。
まずはiOSで実行してみましょう。iOSシミュレータのアプリケーション上でボタンをクリックすると、アルバムから画像を選択するUIが表示されます。
画像を選択すると、画像ファイルがTEMPORARYファイルシステム上に作成されます。その後、ファイルパスとPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いて、PERSISTENTファイルシステム上にファイルを移動します。
なお、実機でファイルがPERSISTENTファイルシステムに移動されているかを確認する場合は、iTunes経由でファイルを取り出してみるのが良いでしょう。XcodeでResources以下の<プロジェクト名>-Info.plistを開き、「Application supports iTunes file sharing」を追加。Valueを[YES]に設定して保存することでファイル共有が有効になります。
続けてAndroidで動作を確認してみます。Androidエミュレータのアプリケーション上でボタンをクリックし、カメラを起動します。写真撮影後のアラートで、ファイルの保存場所を確認します。
リスト1のサンプルコードで行っている処理の流れは次のとおりです。
- requestFileSystemでPERSISTENTファイルシステムを取得
- FileSystemオブジェクトのrootプロパティから、PERSISTENTファイルシステムのルートディレクトリの情報(DirectoryEntryオブジェクト)を取得
- navigator.camera.getPictureを用いて、iOSではアルバムから画像を選択。Androidではカメラを使用して画像ファイルをTEMPORARYファイルシステムに作成
- destinationTypeにCamera.DestinationType.File_URIを指定しているので、コールバック関数にはファイルパスが渡される
- ファイルパスとresolveLocalFileSystemURIを用いて、作成したファイルのFileEntryオブジェクトを取得
- FileEntryオブジェクトのmoveToメソッドと、2で取得したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いてファイル移動
15行目でまずグローバル変数persistentDirectoryEntryを宣言します。アプリケーション起動時に、requestFileSystemメソッドであらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておきます。
45行目ではnavigator.camera.getPictureから渡される、TEMPORARYファイルシステムに作成された画像ファイルのパスを用いて、resolveLocalFileSystemURIでFileEntryオブジェクトを取得します。
resolveLocalFileSystemURIで取得したFileEntryオブジェクトと、アプリケーション起動時に要求したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用い、FileEntryのmoveToメソッドでファイルを移動します。移動成功時には第3引数で指定した関数に移動後のファイル情報がFileEntryオブジェクトで渡されます。
PERSISTENTファイルシステムに、画像ファイルの詳細データを格納したテキストファイルを作成(iOS/Android)
File API Test (3)のソースコード(リスト2)を改変し、画像ファイルをPERSISTENTディレクトリに移動後、画像の詳細データを取得して同階層にテキストファイルとして保存してみましょう。
まずはiOSで実行してみましょう。アルバムから画像を選択し、画像ファイルがTEMPORARYファイルシステム上に作成。PERSISTENTファイルシステムへファイルを移動するところまでは一緒です。ファイル名はタイムスタンプとなるように変更しています。
続けて、画像ファイルの幅、高さ、ファイル名、MIME、最終更新日時、ファイルサイズを取得し、同名のテキストファイルに書き込みます。
同様に、Androidでも実行してみましょう。
AndroidではFileオブジェクトのMIME取得に成功していますが、iOSではなぜかnullになってしまいました。
サンプルコードで行っている処理の流れは次のとおりです。7以降の処理が新規に追加されています。
- requestFileSystemでPERSISTENTファイルシステムを取得
- FileSystemオブジェクトのrootプロパティから、PERSISTENTファイルシステムのルートディレクトリの情報(DirectoryEntryオブジェクト)を取得
- navigator.camera.getPictureを用いて、iOSではアルバムから画像を選択。Androidではカメラを使用して画像ファイルをTEMPORARYファイルシステムに作成
- destinationTypeにCamera.DestinationType.File_URIを指定しているので、コールバック関数にはファイルパスが渡される
- ファイルパスとresolveLocalFileSystemURIを用いて、作成したファイルのFileEntryオブジェクトを取得
- FileEntryオブジェクトのmoveToメソッドと、2で取得したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いてファイル移動
- 移動したあとのFileEntryオブジェクトのfileメソッドで、Fileオブジェクトを作成
- Fileオブジェクトからパス情報を取得し、Imageオブジェクトのsrc属性に格納。Fileオブジェクトに格納されている情報や、画像の幅/高さの情報を取得
- PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて、getFileメソッドで新規にファイルを作成
- 新規に作成したファイルのFileEntryオブジェクトにおいて、createWriterメソッドでFileWriterオブジェクトを作成
- ファイルに8で取得した情報を書き込み。アラートで結果を表示
ファイルの移動成功時に呼び出されるmoveToSuccess関数から見てみましょう。moveToメソッドではファイルの移動成功時に、コールバック関数に移動後のファイル情報を格納しているFileEntryオブジェクトを渡します。
FileEntryのfileメソッドを用いて、Fileオブジェクトを作成します。成功時にコールバック関数--readImageInfoに、Fileオブジェクトを渡します。
Imageオブジェクトのsrc属性に、Fileオブジェクトに格納されているファイルパスを格納します。画像のロードが完了した際に無名関数を呼び出し、画像の幅や高さ・ファイルの名前やサイズといった情報を取得。<pre id="result"></pre>に書き込みます。
その後、あらかじめ取得しておいたPERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいてgetFileメソッドを使用し、新規にファイルを作成します。
第1引数にはファイル名を指定しています。同名のファイルになるように、replaceメソッドで拡張子のみをjpgからtxtに置換します。
第2引数にはFlagsオブジェクトで動作を指定します。各プロパティ値については次のとおりです。
- create
- trueを指定した場合、ファイルやディレクトリが存在しなければ新規に作成します
- exclusive
- trueを指定した場合、ディレクトリが存在しなければ指定した階層まで再帰的に作成します
Flagsオブジェクトのcreateプロパティにtrueを指定していますので、getFileメソッドは同名のファイルが存在しない場合、新規にファイルを作成する動作となります。新規に作成したファイルのFileEntryオブジェクトにおいてcreateWriterメソッドを使用して、ファイルを書き込むためのFileWriterオブジェクトを作成します。
FileWriterオブジェクトの作成に成功した場合、コールバック関数--writingImageInfoにFileWriterオブジェクトを渡します。
FileWriterオブジェクトのseekメソッドでシークポイントを先頭に移動し、writeメソッドで<pre id="result"></pre> の中身を書き込みます。書き込み完了後、結果をアラートで表示します。
FileWriterオブジェクトに用意されているメソッドは次のとおりです。(使い方のfileWriterは、FileWriterオブジェクトを指します)
メソッド名 |
内容 |
使い方 |
abort |
ファイルへの書き込みを中止します。 |
fileWriter.abort() |
seek |
シークポインタをバイト単位で指定します。 |
fileWriter.seek(offset) |
truncate |
指定された長さになるように、ファイルの内容を削除します。 |
fileWriter.truncate(size) |
write |
ファイルにデータを書き込みます。エンコーディングはUTF-8です。 |
fileWriter.write(text) |
次回は、エクスプローラのようなファイル参照機能付きのアプリケーションを作成してFileReaderの使い方を。また、ファイルをネットワーク経由で転送するためのFileTransferオブジェクトについて取りあげていきたいと思います。