2014/09/10

Google App Engineでファイルを保存する方法3つ


Google App Engineでは、通常のWebアプリケーションのように、サーバー上のファイルシステムへアクセスすることができない。別の方法でファイルの読み書きをする事になるけど、方法はいくつかあるので、それぞれの方法と長所短所をまとめてみた。サンプルと全てのソースコードはこちら。(サンプル/ソースコード)

方法1:BlobPropertyを使う

ndb(db)のBlobProperty(https://developers.google.com/appengine/docs/python/ndb/properties)ではバイナリデータをそのまま格納できる。

まずは保存するModelの定義を実装する。
from google.appengine.ext import ndb
class UserFileModel(ndb.Model):
    """
    ファイル格納モデル
    """
    file_data = ndb.BlobProperty()                  # ファイルデータ

続いて、アップロードフォーム。
<form>
<div class="form-group">
<input id="exampleInputFile" name="file_data" type="file" />
    </div>
<button class="btn btn-default" type="submit">保存</button>
</form>

アップロードハンドラを実装。リクエストされたデータをそのまま突っ込むだけ。
def post(self):
        file_data = self.request.get('file_data')
        user_file = UserFileModel()
        user_file.file_data = file_data
        user_file.put()

一番お手軽な方法だけど、1エンティティの上限が1MBまでという制限があるので注意が必要。それより大きいファイルを保存しようとするとこんなエラーが出る。

RequestTooLargeError: The request to API call datastore_v3.Put() was too large.

BlobPropertyではzip圧縮オプション(compressed=True)が使えるので多少容量を抑えることができる。ただ、圧縮しない時よりデータ読み書き時にCPUを消費するのでそこはトレードオフだ。

方法2:Blobstoreを使う

Blobstoreとは、Googleが提供するキー・バリュー型のデータストアサービス。上のBlobPropertyと名前が似てるけど、厳密にはGoogle App Engineとは別領域のサービスだ。

まずはアップロード先URLの生成する。Blobstoreでは、最初にアップロード先のURLを生成しておく必要がある。生成にはgoogle.appengine.ext.blobstoreライブラリの create_upload_url を使う。

upload_url = blobstore.create_upload_url('/file_save/upload2')

引数の /file_save/upload2 は、アップロード後にリダイレクトされるパスを指定する。

続いて、アップロードフォームを実装する。上で生成したアップロードURLがPOST先となるようにする。
<form action="{{ upload_url }}" enctype="multipart/form-data" method="post" role="form">
<div class="form-group">
<input id="exampleInputFile" name="file_data" type="file" />
    </div>
<button class="btn btn-default" type="submit">保存</button>
  </form>

生成したアップロードURLはこんな感じになる。
http://gcp-memo.appspot.com/_ah/upload/AMmfu6aKr-VcNuFlEljprrh7rkbKnBA7WndhyciPTGolHiRkxVq670JENWihVEWViTxRue0K5Y10fOFpmnFzF4hn7qBMIZSn8vhmDT55aO5jNMPqEeQL46R6iWQvEps64_i8WQJsXAHl/ALBNUaYAAAAAVA_q4rzSwstBg1S6i5l3FpfHv4N0EdAR/

/_ah/upload はGoogle App Engineで決まっているシステム用のパスだ。ここでアップロードが行われた後、create_upload_urlで指定したパスに302リダイレクトされる。

アップロード後にリダイレクトされる処理を実装する。ここでBlobstoreに保存したファイルの情報が取れるので、キーを格納したりできる。このハンドラは、google.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandlerクラス を継承しておく必要がある。
class Upload2(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files = self.get_uploads('file_data')
        blob_info = upload_files[0]
        self.redirect('/file_save/upload2_done?key=%s' % blob_info.key())

先にアップロードするURLを生成する必要があったり、アップロード後にリダイレクトされたりとちょっと扱いにくい印象。保存したファイルを参照する方法はまたの機会に。

方法3:Google Cloud Storageを使う

Google Cloud Storageは、Google Cloud Platformで提供されているストレージサービスだ。Google App Engineからも簡単にアクセスすることができる。

アップロードフォーム。
<form action="upload3" enctype="multipart/form-data" method="post" role="form">
<div class="form-group">
<input id="exampleInputFile" name="file_data" type="file" />
  </div>
<button class="btn btn-default" type="submit">保存</button>
  </form>

アプロードハンドラを実装。通常のPythonアプリケーションの様に、ストレージ上のファイルの読み書きができる。ファイル操作には、Googleから提供されている Google Cloud Storage Client Libraryを使用する。(ダウンロードしてGAEアプリケーションに組み込んでおく必要がある)。

また、blobstore.create_gs_key 関数を使用すると、blobstoreライブラリで利用できるキーを生成することができる。blobstoreライブラリを使うと大きめのファイルのダウンロード処理が簡単にできるようになるので覚えておきたい。

関連ライブラリがごちゃごちゃしている感があるけど、通常のファイル操作と同じように扱えるため利用しやすい。
import lib.cloudstorage as gcs
# (中略)
class Upload3(Controller):
    def post(self):
        # ファイル名とファイルデータを得る
        file_name = self.request.POST['file_data'].filename
        file_data = self.request.get('file_data')
        # このアプリケーションのデフォルトGCSバケット名を得る
        bucket_name = app_identity.get_default_gcs_bucket_name()
        # 保存パスを作成
        filepath = '/' + bucket_name + '/file_save/' + file_name
        # ファイル作成
        gcs_file = gcs.open(filepath, 'w')
        gcs_file.write(file_data)
        gcs_file.close()
        gcs_key = blobstore.create_gs_key('/gs' + filepath)
        self.set_template_value('message', gcs_key)
        self.draw_template('front/file_save/done.html')

まとめ

総合的に見るとGoogle Cloud Storageが一番良い。1MB未満のデータで無料枠で収まるようなアプリならBlobPropertyがお手軽でいいかも。Blobstoreを使うメリットは無さそうかな。
方法 扱いやすさ 容量制限 ストレージ価格(GB/月)
BlobProperty 1MB $0.18
Blobstore × 2GB $0.026
Google Cloud Storage ほぼ無制限 $0.026

2 件のコメント:

  1. 大変参考になりました。
    これからもいろんな情報アップしてくださいね♪

    返信削除
  2. The experience is unchanged the rationale that} game is played via a reside video stream in real-time. The Roulette wheel consists of numbers 1 by way of 36, alternately colored red and black, plus zero and 00, which are colored green, for a complete of 38 attainable profitable numbers. The Dealer spins the ball and will call NO MORE BETS prior to the ball dropping. The profitable number is marked and 퍼스트카지노 all shedding bets are removed. First, one needs to develop a clear picture of the logic behind the maths.

    返信削除