2013年07月05日

【Packaged Apps】SyncFileSystemを使ってローカルファイルとリモートファイルを別け隔てなく扱う【Chrome】

Chrome SyncFileSystem APIはとても便利なAPIである。
これを使えば開発者はローカル/リモートのファイルストレージを一つのコードで利用することができるのだ。
これを利用すれば、アプリをオフラインで使っているときはアプリが扱うデータはローカルに保存され、オンラインになると自動的にリモート(Google Drive)と同期させることができるようになる。アプリの利便性が向上すること間違いなし。なんと素晴らしいAPIだろうか。

では早速サンプルコードを見てみよう。
このサンプルアプリも例によって packaged apps プロジェクトとして作ってある。

ファイル構成:
app.js
background.js
calculator-128.png
calculator-16.png
index.html
manifest.json

重要なのは太字の箇所。

まずはmanifest.jsonから見てみよう。
{
  "name": "syncFilesystem sample App",
  "description": "Sample app using the Chrome SyncFilesystem API.",
  "version": "0.1",
  "app": {
    "background": {
      "scripts": ["background.js"]
    }
  },
  "icons": { "16": "calculator-16.png", "128": "calculator-128.png" },
  "permissions": [
    "syncFileSystem"
  ]
}

permissions に "syncFileSystem" を設定しているところが重要。

次に index.html
<!DOCTYPE html>
<html ng-app ng-csp>
<head>
<meta charset='utf-8'>
</head>
<body>
<button id="create_btn">Create a file / append data</button>
<button id="read_btn">Read a file</button>
<button id="remove_btn">Remove a file</button>
<pre id="result"></pre>
<script src="app.js"></script>
</body>
</html>

ファイル作成(ファイル書込)ボタン、ファイル読込ボタン、ファイル削除ボタンの3つのボタンが設置されている。
id="result"なdivには読み込んだファイル内容を表示する。

いよいよお待ちかねの app.js
document.getElementById('create_btn').onclick = function() {

  chrome.syncFileSystem.requestFileSystem(function (fs) {
    fs.root.getFile('test.txt', {create:true}, 
      function(fileEntry){
        fileEntry.createWriter(function(fileWriter) {
          fileWriter.onwriteend = function(e) {
            console.log('fileWriter.onWriteEnd.');
            console.log('fileEntry.fullPath:' + fileEntry.fullPath);
          };
          fileWriter.onerror = function(e) {
            console.log('fileWriter.onError:' + e.toString());
          };
          // 内容にテキトーな文字列(日付)を「追記」
          fileWriter.seek(fileWriter.length); // この行を削除すれば「新規書込モード」になる
          var blob = new window.Blob([new Date() + '\n']);
          fileWriter.write(blob);
        }, 
        function(error){
          console.log('fileEntry.createWriter error:' + error.code);
        });
      }, 
      function(error){
        console.log('syncFileSystem.getFile error:' + error.code);
      }
    );
  });
  
};


document.getElementById('read_btn').onclick = function() {

  chrome.syncFileSystem.requestFileSystem(function (fs) {
    fs.root.getFile('test.txt', {create:false}, 
      function(fileEntry){
        fileEntry.file(function(file){
          // FileReaderを生成
          var reader = new FileReader();
          // ファイルロード完了時処理
          reader.onloadend = function(e){
            var txtArea = document.getElementById('result');
            txtArea.innerText = this.result;
          };
          // FileReaderでテキストを読み込み
          reader.readAsText(file);
          },
          function(error){
            console.log('fileEntry.file error:' + error.code);
          }
        );
      },
      function(error){
        console.log('fileEntry.getFile error:' + error.code);
      }
    );
  });  

};


document.getElementById('remove_btn').onclick = function() {

  chrome.syncFileSystem.requestFileSystem(function (fs) {
    fs.root.getFile('test.txt', {create:false}, 
      function(fileEntry){
        fileEntry.remove(function(){
            console.log('a file removed.');
          },
          function(error){
            console.log('fileEntry.remove error:' + error.code);
          }
        );
      },
      function(error){
        console.log('fileEntry.getFile error:' + error.code);
      }
    );
  });  

};

「新規作成(書込)」、「読込」、「削除」の全ての処理で共通なのは、chrome.syncFileSystem.requestFileSystem(function (fs) {...} 内で fs.root.getFile() するところ。
後は取得した fileEntry で FileWriter を取得して新規作成/書込を行うか、FileReaderを生成して読込を行うか、fileEntry.remove() でファイル削除を行うかすれば良いだけ。
SyncFileSystem API のインターフェースは基本的に FileSystem APIと変わらない。


ちなみにこのサンプルアプリで生成されたデータはどこに保存されているかというと、

まずChromeにGoogleアカウントでログインしていない場合は、
C:\Users\<USERNAME>\AppData\Local\Google\Chrome\User Data\Default\Storage\ext\<APP_ID>\def\File System\000\s\00\00000002
に保存されていて、
ログインしている場合には、
上記のローカルパスとGoogleDriveの両方にファイルが自動保存されている。GoogleDrive上でのパスは、
/Chrome Syncable FileSystem/<APP_ID>/test.txt
となる。


サンプルが動かないとき

このサンプルを試すにはChromeにログインする必要がある。ログインしていないと下のようなエラーメッセージが出てうまく動かないので注意が必要だ。
syncFileSystem.requestFileSystem: Sync: authentication failed. at chrome-extension://fsdfdafsdfdsfsafdsfaadfadsfsadfdsaf/app.js:8:23
作った本人も忘れた頃にハマりました。

参考
Manage Data - Google Chrome
ブラウザーにファイルを残せるFile system APIの使い方 - ASCIIネット
Exploring the FileSystem APIs - HTML5 Rocks


関連エントリ
AngularJSを使って画面遷移、バリデーションなど。
JS用MVCフレームワーク「AngularJS」を使ってChrome Packaged Apps【基本編】
【Chrome】Packaged Apps アプリをHelloWorld【Google】
スマホOSの主導権争いの行方
posted by 寄り道退屈男 at 13:41 | Comment(0) | TrackBack(0) | Packaged Apps
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス: [必須入力]

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/70526762
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック