もっと使おうPhoneGap/Cordova 2.0.0

第6回File APIを使ったiOS/Androidアプリケーション作成その3]

前回は、実際にFile APIを使ってファイルの操作を行う準備について説明しました。今回は前回に続いて以下の操作について紹介します。

  • TEMPORARYファイルシステムのファイル一覧を取得し、画面に表示
  • Camera APIで作成したファイルをPERSISTENTファイルシステムに移動
  • PERSISTENTファイルシステムに、画像ファイルの詳細データを格納したテキストファイルを作成

今回も前回と同様、iOSとAndroid、両OSでの手順を紹介していきます。実機を使用せず、Mac OS上のiOSシミュレータ、Windows上のAndroidエミュレータとPCに接続されているカメラデバイスを用いた手順を紹介します。

TEMPORARYファイルシステムのファイル一覧を取得(iOS/Android)

前回紹介したFile APIのオブジェクト、メソッドを用いて、TEMPORARYファイルシステム上のファイル一覧を取得してみましょう。ソースコードは次のとおりです。

リスト1 ソースコード: File API Test (2)
 1 <!DOCTYPE html>
 2 <html>
 3    <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 5     <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
 6     <title>File API Test (2)</title>
 7   </head>
 8   <body>
 9     <div class="app">
10       <h1>File API Test</h1>
11       <ul id="tempfs_fileList"></ul>
12     </div>
13     <script type="text/javascript" src="cordova-2.0.0.js"></script>
14     <script type="text/javascript">
15     document.addEventListener('deviceready', init, false);
16     function init() {
17       // TEMPORARYファイルシステムを取得
18       window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, getFilesFromDirectory, fail);
19     }
20 
21     function getFilesFromDirectory(fileSystem) {
22       // FileSystemオブジェクトのrootプロパティには、DirectoryEntryオブジェクトが格納されている
23       var directoryEntry = fileSystem.root;
24 
25       // DirecotryEntryオブジェクトのcreateReaderメソッドを使い、
26       // ディレクトリ内のファイルを読み込むためのDirectoryReaderオブジェクトを作成
27       var directoryReader = directoryEntry.createReader();
28 
29       // DirectoryReaderオブジェクトのreadEntriesメソッドを使い、
30       // ディレクトリ内のエントリを読み込み、コールバック関数に配列として渡す
31       directoryReader.readEntries(putFileName, fail);
32     }
33 
34     function putFileName(entries) {
35       // ディレクトリ内のエントリがFileEntryオブジェクトまたは
36       // DirectoryEntryオブジェクトとして配列で渡される
37       for ( index = 0; index < entries.length; index++ ) {
38         // ファイル名を格納する DOM を作成
39         var listItem = document.createElement('li');
40         listItem.textContent = entries[index].name;
41         
42         // 作成した DOM を <ul id="tempfs_fileList"></ul> に挿入
43         document.getElementById('tempfs_fileList').appendChild(listItem);
44       }
45     }
46 
47     function fail(error) {
48       // エラーについては http://docs.phonegap.com/en/2.0.0/cordova_file_file.md.html#FileError を参照
49       alert('エラーが発生しました。エラーコード: ' + error.code);
50     }
51     </script>
52   </body>
53 </html>

このサンプルコードでは、TEMPORARYファイルシステムのファイル一覧を取得し、列挙します。iOSシミュレータ、Androidエミュレータで実行した場合の動作結果は次のとおりです。

iOSシミュレータで実行
iOSシミュレータで実行
Androidエミュレータで実行
Androidエミュレータで実行

リスト1サンプルコードで行っている処理の流れは次のとおりです。

  1. requestFileSystemでTEMPORARYファイルシステムを取得
  2. FileSystemオブジェクトのrootプロパティから、TEMPORARYファイルシステムのルートディレクトリの情報(DirectoryEntryオブジェクト)を取得
  3. DirectoryEntryオブジェクトのcreateReaderメソッドを用いて、DirectoryReaderオブジェクトを作成
  4. DirectoryReaderオブジェクトのreadEntriesメソッドを用いて、ディレクトリ内のファイル/ディレクトリエントリを読み込む
  5. readEntriesメソッドから渡されたFileEntry/DirectoryEntryの配列を受け取り、ファイル名を<li>要素で列挙

第4回の記事を参照し、各オブジェクトの関係性や処理の流れを把握しておくと理解しやすいでしょう。

18行目のrequestFileSystemメソッドは、PERSISTENTまたはTEMPORARYのどちらかのFileSystemオブジェクトを取得します。第3引数で指定したgetFilesFromDirectory関数に、取得したFileSystemオブジェクトが渡されます。

18  window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, getFilesFromDirectory, fail);

FileSystemオブジェクトのrootプロパティには、DirectoryEntryオブジェクトが格納されています。DirectoryEntryオブジェクトのcreateReaderメソッドを用いて、TEMPORARYファイルシステム、ルートディレクトリ内のディレクトリ・ファイルを読み込むためのオブジェクト--DirectoryReaderオブジェクトを作成し、directoryReader変数に格納します。

22  // FileSystemオブジェクトのrootプロパティには、DirectoryEntryオブジェクトが格納されている
23  var directoryEntry = fileSystem.root;
24  
25  // DirecotryEntryオブジェクトのcreateReaderメソッドを使い、
26  // ディレクトリ内のファイルを読み込むためのDirectoryReaderオブジェクトを作成
27  var directoryReader = directoryEntry.createReader();

DirectoryReaderオブジェクトには1つだけメソッドが用意されています。ディレクトリ内のエントリを読み込むメソッド--readEntriesメソッドを用いて、ディレクトリ内のディレクトリ・ファイル情報を第1引数で指定したputFileName関数に渡します。

29  // DirectoryReaderオブジェクトのreadEntriesメソッドを使い、
30  // ディレクトリ内のエントリを読み込み、コールバック関数に配列として渡す
31  directoryReader.readEntries(putFileName, fail);

あるディレクトリ内にディレクトリが1つ、ファイルが3つある場合には、次のような配列がコールバック関数に渡されます。

[<DirectoryEntry>, <FileEntry>, <FileEntry>, <FileEntry>]

putFileName関数はDirectoryEntry/FileEntryが格納された配列を受け取り、for文で配列の要素の数だけDOMを作成して、ディレクトリ名/ファイル名を列挙します。

34  function putFileName(entries) {
35    // ディレクトリ内のエントリがFileEntryオブジェクトまたは
36    // DirectoryEntryオブジェクトとして配列で渡される
37    for ( index = 0; index < entries.length; index++ ) {
38      // ファイル名を格納する DOM を作成
39      var listItem = document.createElement('li');
40      listItem.textContent = entries[index].name;
41      
42      // 作成した DOM を <ul id="tempfs_fileList"></ul> に挿入
43      document.getElementById('tempfs_fileList').appendChild(listItem);
44    }
45  }

fail関数はFile APIでファイルを操作している場合にエラーが起こった際に呼び出される関数です。FileErrorオブジェクトを受け取り、エラーコードを表示します。数値とエラーコードの対応は次のとおりです。

// cordova-2.0.0.js 2180-2195
// File error codes
// Found in DOMException
FileError.NOT_FOUND_ERR = 1; 
FileError.SECURITY_ERR = 2; 
FileError.ABORT_ERR = 3; 

// Added by File API specification
FileError.NOT_READABLE_ERR = 4; 
FileError.ENCODING_ERR = 5; 
FileError.NO_MODIFICATION_ALLOWED_ERR = 6; 
FileError.INVALID_STATE_ERR = 7; 
FileError.SYNTAX_ERR = 8; 
FileError.INVALID_MODIFICATION_ERR = 9; 
FileError.QUOTA_EXCEEDED_ERR = 10;
FileError.TYPE_MISMATCH_ERR = 11;
FileError.PATH_EXISTS_ERR = 12;

Camera APIで作成したファイルをPERSISTENTファイルシステムに移動(iOS/Android)

Camera APIで作成されるファイルを、PERSISTENTファイルシステムに移動してみましょう。Camera APIからファイルパスが渡されるので、resolveLocalFileSystemURIメソッドを用いるのが便利です。

ソースコードは次のとおりです。

リスト2 ソースコード: File API Test (3)
 1  <!DOCTYPE html>
 2  <html>
 3    <head>
 4      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 5      <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
 6      <title>File API Test (3)</title>
 7    </head>
 8    <body>
 9      <div class="app">
10        <h1>File API Test</h1>
11        <input type="button" value="Camera API" id="camera">
12      </div>
13      <script type="text/javascript" src="cordova-2.0.0.js"></script>
14      <script type="text/javascript">
15      var persistentDirectoryEntry;
16      document.addEventListener('deviceready', init, false);
17  
18      function init() {
19        // あらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておく
20        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getPersistentDirectoryEntry, failFS);
21   
22        document.getElementById('camera').addEventListener('click', camera, false);
23      }
24  
25      function getPersistentDirectoryEntry(fileSystem) {
26        persistentDirectoryEntry = fileSystem.root;
27      }
28  
29      function camera() {
30        sourceType = Camera.PictureSourceType.PHOTOLIBRARY;
31        if ( 'Android' === device.platform ) {
32          sourceType = Camera.PictureSourceType.CAMERA;
33        }
34        navigator.camera.getPicture(getPictureSuccess, failCamera,
35        {
36          quality: 50, 
37          destinationType: Camera.DestinationType.File_URI,
38          sourceType: sourceType
39        });
40      }
41  
42      function getPictureSuccess(uri) {
43        // Camera APIから渡されるファイルパスと、resolveLocalFileSystemURIメソッドを用いて
44        // TEMPORARYファイルシステムに作成された画像ファイルのFileEntryオブジェクトを取得する
45        window.resolveLocalFileSystemURI(uri, moveToPersistent, failFS);
46      } 
47  
48      function moveToPersistent(fileEntry) {
49        // あらかじめ取得しておいたPERSISTENTファイルシステムのDirectoryEntryオブジェクトと
50        // resolveLocalFileSystemURIメソッドで取得したFileEntryオブジェクトを用いて、ファイルをPERSISTENTに移動
51        fileEntry.moveTo(persistentDirectoryEntry, fileEntry.name, moveToSuccess, failFS);
52      }
53  
54      function moveToSuccess(fileEntry) {
55        alert('画像ファイル「' + fileEntry.name + '」を移動しました。\n' + fileEntry.fullPath);
56      }
57  
58      function failCamera(message) {
59        alert('カメラ操作に失敗しました。\n' + message);
60      }
61  
62      function failFS(error) {
63        alert('ファイルシステム操作に失敗しました。\nエラーコード: ' + error.code);
64      }
65      </script>
66    </body>
67  </html>

まずはiOSで実行してみましょう。iOSシミュレータのアプリケーション上でボタンをクリックすると、アルバムから画像を選択するUIが表示されます。

アルバムから画像を選択
アルバムから画像を選択

画像を選択すると、画像ファイルがTEMPORARYファイルシステム上に作成されます。その後、ファイルパスとPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いて、PERSISTENTファイルシステム上にファイルを移動します。

ファイルの移動に成功するとアラートでその旨が通知される
ファイルの移動に成功するとアラートでその旨が通知される
ターミナルでPERSISTENT(Documents/以下)にファイルが移動されていることを確認
ターミナルでPERSISTENT(Documents/以下)にファイルが移動されていることを確認

なお、実機でファイルがPERSISTENTファイルシステムに移動されているかを確認する場合は、iTunes経由でファイルを取り出してみるのが良いでしょう。XcodeでResources以下の<プロジェクト名>-Info.plistを開き、⁠Application supports iTunes file sharing」を追加。Valueを[YES]に設定して保存することでファイル共有が有効になります。

「Application supports iTunes file sharing」を追加し、iTunesファイル共有を有効に
「Application supports iTunes file sharing」を追加し、iTunesファイル共有を有効に

続けてAndroidで動作を確認してみます。Androidエミュレータのアプリケーション上でボタンをクリックし、カメラを起動します。写真撮影後のアラートで、ファイルの保存場所を確認します。

撮影した写真がPERSISTENT(/mnt/sdcard以下)に移動されていることを確認
撮影した写真がPERSISTENT(/mnt/sdcard以下)に移動されていることを確認
EclipseのDDMS、File Explorerで/mnt/sdcard以下に画像ファイルが移動されていることを確認
EclipseのDDMS、File Explorerで/mnt/sdcard以下に画像ファイルが移動されていることを確認

リスト1のサンプルコードで行っている処理の流れは次のとおりです。

  1. requestFileSystemでPERSISTENTファイルシステムを取得
  2. FileSystemオブジェクトのrootプロパティから、PERSISTENTファイルシステムのルートディレクトリの情報(DirectoryEntryオブジェクト)を取得
  3. navigator.camera.getPictureを用いて、iOSではアルバムから画像を選択。Androidではカメラを使用して画像ファイルをTEMPORARYファイルシステムに作成
  4. destinationTypeにCamera.DestinationType.File_URIを指定しているので、コールバック関数にはファイルパスが渡される
  5. ファイルパスとresolveLocalFileSystemURIを用いて、作成したファイルのFileEntryオブジェクトを取得
  6. FileEntryオブジェクトのmoveToメソッドと、2で取得したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いてファイル移動

15行目でまずグローバル変数persistentDirectoryEntryを宣言します。アプリケーション起動時に、requestFileSystemメソッドであらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておきます。

19  // あらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておく
20  window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getPersistentDirectoryEntry, failFS);

…

25  function getPersistentDirectoryEntry(fileSystem) {
26    persistentDirectoryEntry = fileSystem.root;
27  }

45行目ではnavigator.camera.getPictureから渡される、TEMPORARYファイルシステムに作成された画像ファイルのパスを用いて、resolveLocalFileSystemURIでFileEntryオブジェクトを取得します。

45  window.resolveLocalFileSystemURI(uri, moveToPersistent, failFS);

resolveLocalFileSystemURIで取得したFileEntryオブジェクトと、アプリケーション起動時に要求したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用い、FileEntryのmoveToメソッドでファイルを移動します。移動成功時には第3引数で指定した関数に移動後のファイル情報がFileEntryオブジェクトで渡されます。

51  fileEntry.moveTo(persistentDirectoryEntry, fileEntry.name, moveToSuccess, failFS);

PERSISTENTファイルシステムに、画像ファイルの詳細データを格納したテキストファイルを作成(iOS/Android)

File API Test (3)のソースコードリスト2を改変し、画像ファイルをPERSISTENTディレクトリに移動後、画像の詳細データを取得して同階層にテキストファイルとして保存してみましょう。

リスト3 ソースコード: File API Test (4)
  1  <!DOCTYPE html>
  2  <html>
  3    <head>
  4      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  5      <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width;" />
  6      <title>File API Test (4)</title>
  7    </head>
  8    <body>
  9      <div class="app">
 10        <h1>File API Test</h1>
 11        <input type="button" value="Camera API" id="camera">
 12        <img id="image" style="display: none;">
 13        <pre id="result"></pre>
 14      </div>
 15      <script type="text/javascript" src="cordova-2.0.0.js"></script>
 16      <script type="text/javascript">
 17      var persistentDirectoryEntry;
 18      document.addEventListener('deviceready', init, false);
 19  
 20      function init() {
 21        // あらかじめPERSISTENTファイルシステムを要求し、DirectoryEntryオブジェクトを取得しておく
 22        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, getPersistentDirectoryEntry, failFS);
 23        document.getElementById('camera').addEventListener('click', camera, false);
 24      }
 25  
 26      function getPersistentDirectoryEntry(fileSystem) {
 27        persistentDirectoryEntry = fileSystem.root;
 28      }
 29  
 30      function camera() {
 31        sourceType = Camera.PictureSourceType.PHOTOLIBRARY;
 32        if ( 'Android' === device.platform ) {
 33          sourceType = Camera.PictureSourceType.CAMERA;
 34        }
 35        navigator.camera.getPicture(getPictureSuccess, failCamera,
 36        {
 37          quality: 50, 
 38          destinationType: Camera.DestinationType.File_URI,
 39          sourceType: sourceType
 40        });
 41      }
 42  
 43      function getPictureSuccess(uri) {
 44        // Camera APIから渡されるファイルパスと、resolveLocalFileSystemURIメソッドを用いて
 45        // TEMPORARYファイルシステムに作成された画像ファイルのFileEntryオブジェクトを取得する
 46        window.resolveLocalFileSystemURI(uri, moveToPersistent, failFS);
 47      } 
 48  
 49      function moveToPersistent(fileEntry) {
 50        filename = new Date().getTime() + '.jpg';
 51        
 52        // あらかじめ取得しておいたPERSISTENTファイルシステムのDirectoryEntryオブジェクトと
 53        // resolveLocalFileSystemURIメソッドで取得したFileEntryオブジェクトを用いて、ファイルをPERSISTENTに移動
 54        fileEntry.moveTo(persistentDirectoryEntry, filename, moveToSuccess, failFS);
 55      }
 56  
 57      function moveToSuccess(fileEntry) {
 58        // Fileオブジェクトを作成
 59        fileEntry.file(readImageInfo, failFS);
 60      }
 61  
 62      function readImageInfo(file) {
 63        // Imageオブジェクトを取得し、srcにFileオブジェクトのパス情報を代入
 64        var imageObj = document.getElementById('image');
 65        imageObj.src = file.fullPath;
 66  
 67        imageObj.onload = function() {
 68          // 画像のロード完了後、<pre id="result"></pre> に画像情報を書き込み
 69          document.getElementById('result').textContent = 
 70            'width: ' + this.naturalWidth + '\n' + 
 71            'height: ' + this.naturalHeight + '\n' +
 72            'name: ' + file.name + '\n' + 
 73            'type: ' + file.type + '\n' + 
 74            'lastModifiedDate: ' + file.lastModifiedDate + '\n' + 
 75            'size: ' + file.size;
 76  
 77          // PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて
 78          // getFileメソッドを使用して、新規にファイルを作成
 79          persistentDirectoryEntry.getFile(file.name.replace('.jpg', '.txt'), {create: true, reclusive: false}, newFileEntry, failFS);
 80        }
 81      }
 82  
 83      function newFileEntry(fileEntry) {
 84        // 新規に作成したファイルのFileEntryオブジェクトにおいて
 85        // createWriterメソッドを使用して、ファイルを書き込むためのFileWriterオブジェクトを作成
 86        fileEntry.createWriter(writingImageInfo, failFS);
 87      }
 88  
 89      function writingImageInfo(fileWriter) {
 90        // FileWriterオブジェクトを受け取り、シークポイントを先頭に移動
 91        fileWriter.seek(0);
 92        
 93        // <pre id="result"></pre> の中身を書き込み
 94        fileWriter.write(document.getElementById('result').textContent);
 95  
 96        // 書き込み完了時にアラートを表示
 97        fileWriter.onwriteend = function() {
 98          alert('画像の情報を' + fileWriter.fileName + 'に書き出しました。');
 99        }
100      }
101  
102      function failCamera(message) {
103        alert('カメラ操作に失敗しました。\n' + message);
104      }
105  
106      function failFS(error) {
107        alert('ファイルシステム操作に失敗しました。\nエラーコード: ' + error.code);
108      }
109      </script>
110    </body>
111  </html>

まずはiOSで実行してみましょう。アルバムから画像を選択し、画像ファイルがTEMPORARYファイルシステム上に作成。PERSISTENTファイルシステムへファイルを移動するところまでは一緒です。ファイル名はタイムスタンプとなるように変更しています。

続けて、画像ファイルの幅、高さ、ファイル名、MIME、最終更新日時、ファイルサイズを取得し、同名のテキストファイルに書き込みます。

選択した画像の情報を、画像ファイルと同名のテキストファイルに書き込み
選択した画像の情報を、画像ファイルと同名のテキストファイルに書き込み
pre要素内に画像情報を表示
pre要素内に画像情報を表示
ターミナルのcatコマンドでテキストファイルの中身を確認。File APIでファイルの書き込みに成功していることがわかる
ターミナルのcatコマンドでテキストファイルの中身を確認。File APIでファイルの書き込みに成功していることがわかる

同様に、Androidでも実行してみましょう。

撮影した画像の情報を、画像ファイルと同名のテキストファイルに書き込み
撮影した画像の情報を、画像ファイルと同名のテキストファイルに書き込み
コマンドプロンプトでadb shellでSSH接続を行い、catコマンドでテキストファイルの中身を確認
コマンドプロンプトでadb shellでSSH接続を行い、catコマンドでテキストファイルの中身を確認

AndroidではFileオブジェクトのMIME取得に成功していますが、iOSではなぜかnullになってしまいました。

サンプルコードで行っている処理の流れは次のとおりです。7以降の処理が新規に追加されています。

  1. requestFileSystemでPERSISTENTファイルシステムを取得
  2. FileSystemオブジェクトのrootプロパティから、PERSISTENTファイルシステムのルートディレクトリの情報(DirectoryEntryオブジェクト)を取得
  3. navigator.camera.getPictureを用いて、iOSではアルバムから画像を選択。Androidではカメラを使用して画像ファイルをTEMPORARYファイルシステムに作成
  4. destinationTypeにCamera.DestinationType.File_URIを指定しているので、コールバック関数にはファイルパスが渡される
  5. ファイルパスとresolveLocalFileSystemURIを用いて、作成したファイルのFileEntryオブジェクトを取得
  6. FileEntryオブジェクトのmoveToメソッドと、2で取得したPERSISTENTファイルシステムのDirectoryEntryオブジェクトを用いてファイル移動
  7. 移動したあとのFileEntryオブジェクトのfileメソッドで、Fileオブジェクトを作成
  8. Fileオブジェクトからパス情報を取得し、Imageオブジェクトのsrc属性に格納。Fileオブジェクトに格納されている情報や、画像の幅/高さの情報を取得
  9. PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて、getFileメソッドで新規にファイルを作成
  10. 新規に作成したファイルのFileEntryオブジェクトにおいて、createWriterメソッドでFileWriterオブジェクトを作成
  11. ファイルに8で取得した情報を書き込み。アラートで結果を表示

ファイルの移動成功時に呼び出されるmoveToSuccess関数から見てみましょう。moveToメソッドではファイルの移動成功時に、コールバック関数に移動後のファイル情報を格納しているFileEntryオブジェクトを渡します。

57  function moveToSuccess(fileEntry) {
58    // Fileオブジェクトを作成
59    fileEntry.file(readImageInfo, failFS);
60  }

FileEntryのfileメソッドを用いて、Fileオブジェクトを作成します。成功時にコールバック関数--readImageInfoに、Fileオブジェクトを渡します。

62  function readImageInfo(file) {
63    // Imageオブジェクトを取得し、srcにFileオブジェクトのパス情報を代入
64    var imageObj = document.getElementById('image');
65    imageObj.src = file.fullPath;
66  
67    imageObj.onload = function() {
68      // 画像のロード完了後、<pre id="result"></pre> に画像情報を書き込み
69      document.getElementById('result').textContent = 
70        'width: ' + this.naturalWidth + '\n' + 
71        'height: ' + this.naturalHeight + '\n' +
72        'name: ' + file.name + '\n' + 
73        'type: ' + file.type + '\n' + 
74        'lastModifiedDate: ' + file.lastModifiedDate + '\n' + 
75        'size: ' + file.size;
76  
77      // PERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいて
78      // getFileメソッドを使用して、新規にファイルを作成
79      persistentDirectoryEntry.getFile(file.name.replace('.jpg', '.txt'), {create: true, reclusive: false}, newFileEntry, failFS);
80    }
81  }

Imageオブジェクトのsrc属性に、Fileオブジェクトに格納されているファイルパスを格納します。画像のロードが完了した際に無名関数を呼び出し、画像の幅や高さ・ファイルの名前やサイズといった情報を取得。<pre id="result"></pre>に書き込みます。

その後、あらかじめ取得しておいたPERSISTENTファイルシステムのDirectoryEntryオブジェクトにおいてgetFileメソッドを使用し、新規にファイルを作成します。

79  persistentDirectoryEntry.getFile(file.name.replace('.jpg', '.txt'), {create: true, reclusive: false}, newFileEntry, failFS);

第1引数にはファイル名を指定しています。同名のファイルになるように、replaceメソッドで拡張子のみをjpgからtxtに置換します。

第2引数にはFlagsオブジェクトで動作を指定します。各プロパティ値については次のとおりです。

create
trueを指定した場合、ファイルやディレクトリが存在しなければ新規に作成します
exclusive
trueを指定した場合、ディレクトリが存在しなければ指定した階層まで再帰的に作成します

Flagsオブジェクトのcreateプロパティにtrueを指定していますので、getFileメソッドは同名のファイルが存在しない場合、新規にファイルを作成する動作となります。新規に作成したファイルのFileEntryオブジェクトにおいてcreateWriterメソッドを使用して、ファイルを書き込むためのFileWriterオブジェクトを作成します。

83  function newFileEntry(fileEntry) {
84    // 新規に作成したファイルのFileEntryオブジェクトにおいて
85    // createWriterメソッドを使用して、ファイルを書き込むためのFileWriterオブジェクトを作成
86    fileEntry.createWriter(writingImageInfo, failFS);
87  }

FileWriterオブジェクトの作成に成功した場合、コールバック関数--writingImageInfoにFileWriterオブジェクトを渡します。

FileWriterオブジェクトのseekメソッドでシークポイントを先頭に移動し、writeメソッドで<pre id="result"></pre> の中身を書き込みます。書き込み完了後、結果をアラートで表示します。

 89  function writingImageInfo(fileWriter) {
 90    // FileWriterオブジェクトを受け取り、シークポイントを先頭に移動
 91    fileWriter.seek(0);
 92    
 93    // <pre id="result"></pre> の中身を書き込み
 94    fileWriter.write(document.getElementById('result').textContent);
 95  
 96    // 書き込み完了時にアラートを表示
 97    fileWriter.onwriteend = function() {
 98      alert('画像の情報を' + fileWriter.fileName + 'に書き出しました。');
 99    }
100  }

FileWriterオブジェクトに用意されているメソッドは次のとおりです。(使い方のfileWriterは、FileWriterオブジェクトを指します)

メソッド名 内容
使い方
abort ファイルへの書き込みを中止します。
fileWriter.abort()
seek シークポインタをバイト単位で指定します。
fileWriter.seek(offset)
truncate 指定された長さになるように、ファイルの内容を削除します。
fileWriter.truncate(size)
write ファイルにデータを書き込みます。エンコーディングはUTF-8です。
fileWriter.write(text)

次回は、エクスプローラのようなファイル参照機能付きのアプリケーションを作成してFileReaderの使い方を。また、ファイルをネットワーク経由で転送するためのFileTransferオブジェクトについて取りあげていきたいと思います。

おすすめ記事

記事・ニュース一覧