7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google App Engine + Python アプリから Cloud Storage を利用する

Last updated at Posted at 2018-02-16

※2016年7月4日に書いたブログ記事からの転記です。

Cloud Storage を利用可能にしておく

まず最初に、Google Cloud Console から Cloud Storage を使用できるように初期設定しておく必要があります。
初期設定は「利用開始」を選択して「バケットを作成」しておくだけです。
デフォルトのバケットを作成してそれを使用してもよいですし、新たにバケットを作成してもOKです。

Cloud Storafe クライアント・ライブラリをダウンロードする

App Engine Python アプリから Cloud Storage を利用するには、まず最初に Google Cloud Storage クライアント・ライブラリをダウンロードする必要があります。その方法は3つあります。

(1)Github から ZIP をダウンロードする:Google Cloud Storage client library on GitHub

(2)GitHub から clone する:

git clone https://github.com/GoogleCloudPlatform/appengine-gcs-client.git

(3)PIP からインストールする:

pip install GoogleAppEngineCloudStorageClient -t <your_app_directory/lib>

自分の場合は(1)の方法でダウンロードしました。
ダウンロードしたファイルを解凍して、python → src → cloudstorage というフォルダを app_id/lib に配置します。

app_id/
  lib/
  cloudstorage/

さて、これで準備は整いました。

リクエストハンドラーを記述する

プログラムの大まかな流れは次のとおりです。

(1)ブラウザからファイルを受け取る。
(2)受け取ったファイルを Cloud Storage へ保存する。
(3)Cloud Storage での保存先を Datastore に保存する。
(4)Cloud Storage に保存したファイルを表示する。

まずはフォームの HTML です。

<html>
  <body>
    <form method="post" action="" enctype="multipart/form-data">
      <label for="inputTitle">タイトル</label>
      <input type="text" name="title" id="inputTitle">
      <label for="inputFile">ファイル</label>
      <input type="file" name="file" id="inputFile">
    </form>
  </body>
</html>

次に、このフォームから送信されるデータを受け取る POST のリクエストハンドラーです。

from google.appengine.ext import ndb

from google.appengine.ext import blobstore
from lib import cloudstorage as gcs

# Cloud Storage に保存したファイルのパスを保持するための Datastore モデル
class File(ndb.Model):
    path = ndb.StringProperty()
    type = ddb.StringProperty()

class AdminCreateFileHandler(BaseHandler):
    def get(self):
        context = {}
        self.render_template('file.html', **context)  # 上記のフォームのHTMLを表示

    def post(self):
        title = self.request.get('title')
        file_data = self.request.get('file')
        file_name = self.request.POST['file'].filename
        file_type = self.request.POST['file'].type

        # フォームから受け取ったファイルをCloud Storageに保存
        if file_data:
            bucket_name = os.environ.get(
                "GCS_BUCKET_NAME",  # app.yaml に環境変数としてバケット名があればそれを使用
                app_identity.get_default_gcs_bucket_name())  # なければデフォルトのバケット名を使用

            file_path = '/' + bucket_name + '/files/' + file_name
            with gcs.open(file_path, 'w') as gcs_file:
                gcs_file.write(file_data)

        # Cloud Storage での保存先をDatastoreに保存
        file_key = File(
            path=file_path,
            type=file_type,
            title=title,
        ).put()

        self.redirect('/files/%s' % file_key.urlsafe())  # 適当なURLへリダイレクト

最後に、Cloud Storage に保存したファイルを表示するハンドラーです。

from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers

class RequestHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, gcs_path):
      gs_key = blobstore.create_gs_key('/gs' + gcs_path)
      self.send_blob(gs_key)

このハンドラーを routes 内で

Route(
    r'/gcs<gcs_path:/.+>',
    handler='handlers.gcs.RequestHandler',
)

といった感じのURLにマッピングしてあげます。

ファイルを表示

ファイルを表示したい場合は、テンプレートに以下のように記述します。

<img src="/gcs{{ file.path }}">
<!--file は File モデルのエンティティ-->

以上です。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?