2012年8月2日木曜日

GAE/GでGoogle Cloud Storageを利用するには(1)

いろいろ都合があって、GAE/Gから、Google Cloud Storageを利用してみたので
利用方法をメモしておきます。
GAE/GのFileServiceはなぜか、ドキュメントに記載されていない(8/2現在)ので、
GAE/GのSDKのソースコードを見て使い方を理解する必要があります。
(もしくは、Python版、Java版のプログラムから推測するとか…)
ということで、時間がある時にいじって、Blogにメモしようと思います。

1. Google API Consoleで課金設定をONにする。

Google Cloud Storageは課金設定をONにしないと、書き込みも読み込みも、Bucketの作成さえもできないようなので、課金をONにします。

課金をONにしないとIO_ERRORになってしまいます。

※ローカル環境では、何もしなくても実行可能なので、ローカルでしか動かさないという人は、この手順は不要です。

2. Google APIs ConsoleのTeamにサービスのアカウントを追加する。

GAEのアプリケーションからアクセスさせるためには、API Consoleにサービスのアカウントを追加しなければPERMISSION_DENIEDでエラーになります。

サービスのアカウントの場所は、http://appengine.google.comのGAEのアプリケーションにある、
Application→Application Settingsを開きBasic(一番上)のService Account Nameにあるので、書かれているアカウントをコピーします。

[app-id]@appspot.gserviceaccount.com

みたいなものが、書かれていると思います。
(app-idは作成したappidが書かれています。)

Google APIs ConsoleのTeamのところに、ペーストして、権限設定をして追加すれば完了です。


※ローカル環境では、何もしなくても実行可能なので、ローカルでしか動かさないという人は、この手順は不要です。


3. Go言語でプログラムを作成し、デプロイする。

package controller

import (
 "appengine"
 "appengine/file"
 "fmt"
 "net/http"
)

func init() {
 http.HandleFunc("/", list)
}

func list(w http.ResponseWriter, r *http.Request) {
 c := appengine.NewContext(r)

 name, err := file.DefaultBucketName(c); 
 if err != nil {
  http.Error(w, err.Error(), http.StatusInternalServerError)
 } else {
  fmt.Fprintf(w, "DefaultBucketName = %s", name)
 }

 options := new(file.CreateOptions)
 options.MIMEType = "text/plain"
 options.BucketName = "yourBucketName"

// if wc, absFileName, cErr := file.Create(c, "/gs/yourBucketName/test/sample.txt", options); cErr != nil {
 if wc, absFileName, cErr := file.Create(c, "test/sample.txt", options); cErr != nil {
  fmt.Fprintf(w, "Create Error")
  fmt.Fprintf(w, " %s", absFileName)
  c.Debugf("Create Error %s [%s]", cErr.Error(), absFileName)
 } else {
  fmt.Fprintf(w, "Create Success")
  fmt.Fprintf(w, " %s", absFileName)

  if _, wErr := wc.Write([]byte("Sample Text")); wErr != nil {
   c.Debugf("Write Error = %s", wErr.Error())
  }

  wc.Close()

  if fi, statErr := file.Stat(c, absFileName); statErr != nil {
   c.Debugf("%s", statErr.Error())
  } else {
   c.Debugf("%s %d", fi.Name(), fi.Size())
  }
 }

}

4. 実行

上記のプログラムを実行すると、作成したBucketの中のtestフォルダの中にsample.txtが
作成されていると思います。

GAE/Gだと、file.CreateOptionsにBucketNameが指定されていないと、デフォルトの
BucketNameが設定される様になっているのですが、本番環境では、""(空文字列)なので
作成時にエラーになると思います。(BucketNameは必ず指定する必要があるので)
(ちなみに、ローカル環境だと"app_default_bucket"というのが設定されます)

後は、プログラムを見れば大体わかると思いますが、ファイル作成時は、絶対パス指定でも、
相対パス指定でもファイルの参照は可能です。

絶対パス指定の場合は、先頭に"/gs"をつける必要があります。
書式は「/gs/[Bucket名]/フォルダ名/ファイル名」となります。
フォルダ名を省略すれば、Bucketの直下(という表現が正しいのか?)に作成されると思います。

ということで、課金が恐ろしいですが、
1GBあたり、$0.12とか、$0.01とか、ある程度のところまでは、円高のおかげでうまい棒程度で済みそうなので
いろいろいじってみたいと思います。
(参考:https://developers.google.com/storage/docs/pricingandterms?hl=ja


2012年8月1日水曜日

Google Apps ScriptでGoogle DriveのファイルリストをDashBoardに表示する

Google Apps ScriptのTutorialに、DashBoardのチュートリアルがあったので、
サンプルを入力して実行してみました。

簡単にデータの一覧と円グラフが表示できて、しかも、フィルタもつけることができます。
DashBoardの機能を使うことで、いろいろなデータを解析するのに役に立つかもしれません。

サンプルを元に、Google Driveにある資料のリストを取得して、リストに出す。

というのを作ってみました。
ソースコードを添付しておきます。

function doGet() {
  // Google Driveのリストを取得し、DataTableを生成
  var files = DocsList.getFiles();
  
  var dataTable = Charts.newDataTable();
  dataTable.addColumn(Charts.ColumnType.STRING, "FileType");
  dataTable.addColumn(Charts.ColumnType.NUMBER, "Size");
  dataTable.addColumn(Charts.ColumnType.DATE, "Create");
  dataTable.addColumn(Charts.ColumnType.DATE, "LastUpdate");
  
  for(var i in files) {
    var row = [];
    row.push(files[i].getFileType().toString());
    row.push(Number(files[i].getSize()));
    row.push(files[i].getDateCreated());
    row.push(files[i].getLastUpdated());

    dataTable.addRow(row);
  }
  var data = dataTable.build();
  
  // FileTypeでのフィルタ
  var typeFilter = Charts.newCategoryFilter()
      .setFilterColumnLabel("FileType")
      .build();
    
  var tableChart = Charts.newTableChart().build();
  
  var dashboard = Charts.newDashboardPanel()
      .setDataTable(data)
      .bind(typeFilter, tableChart)
      .build();
  
  var app = UiApp.createApplication();
  dashboard.add(
    app.createVerticalPanel()
    .add(typeFilter)
    .add(tableChart)
    .setSpacing(30)
  );
  
  app.add(dashboard);
  
  return app;
}

サンプルでは、日付の列がなかったので、今回は作成日と最終更新日を取得するようにしています。
また、データが定数だったので、このソースコードでは、データを動的に追加するようにもしています。
(定数での挙動と、メソッドの戻り値での挙動で少しハマったので、気をつけて下さい。)

日付の列に関しては、Date型のオブジェクトを渡せば良いので、そんなに難しくはないですが、
文字列と、数値に関しては、それぞれ、StringとNumberに変換する必要があるので
その対応が必要になります。
(定数だと、暗黙型変換でいい感じになるみたい)

オブジェクトだと、Object.toString()を使い、数値だとNumber()を使って型を変換しておきます。
私はこの型変換ではまりました。

今のところ、日付によるフィルタというのは存在しない(?)みたいです。
本当は、期間別のデータを表示してみたりしたかったのですが…。

他にもいろんなグラフが表示できるので試してみて下さい。