susukinosu

エンジニアリングって、何だよ

Google App Engine / Python で、ブロブストアを利用した画像編集って…

Google App Engine(GAE)をPythonで利用するチュートリアルをこなしてます。
ちなみにPythonに関しては初学者程度の技能しか持ちあわせてないです。

チュートリアルにおいて、
「メインハンドラ」
「アップロードハンドラ」
「ダウンロードハンドラ」


のクラスを作成して、画像などを
hogeapp/serve/内にアップロード、ダウンロードハンドラにて、アップロード先のURLを表示させる
といったテストができた。

これはデータストアを利用した場合であり、
画像や動画などの大容量ファイルを利用する際は、「ブロブストア」が推奨される。

〜〜〜〜

さて、本題

#! -*- coding:utf-8 -*-

import os
import urllib

from google.appengine.ext import blobstore
from google.appengine.ext import webapp
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app

class MainHandler(webapp.RequestHandler):
    def get(self):
        upload_url = blobstore.create_upload_url('/upload')
        self.response.out.write('<html><body>')
        self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
        self.response.out.write("""<div align="center"><h2>アップロードしたい画像を選択してください</h2></div><hr>""")
        self.response.out.write("""<input type="file" name="file"><br> <input type="submit" name="submit" value="アップロード"> </form></body></html>""")

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
        blob_info = upload_files[0]
        self.redirect('/serve/%s' % blob_info.key())

class Thumbnailer(blobstore_handlers.BlobstoreUploadHandler):
    def get(self, source):
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)

        img = images.Image(blob_info=blob_info)
        img.resize(width=80, height=100)
        img.im_feeling_lucky()
        thumbnail = img.execute_transforms(output_encoding=images.JPEG)

        from google.appengine.ext import webapp.RequestHandler
        self.response.headers['Content-Type'] = 'image/jpeg'
        self.response.out.write(thumbnail)

        self.redirect('/serve/%s' % blob_info.key())

class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        self.send_blob(blob_info)

def main():
    application = webapp.WSGIApplication(
          [('/', MainHandler),
           ('/upload', UploadHandler),
           ('/serve/([^/]+)?', ServeHandler),
          ], debug=True)
    run_wsgi_app(application)

if __name__ == '__main__':
  main()

わからないなりに組み立ててみましたが、
このままだと画像が変換されないまま、オリジナルの画像として表示されます。

画像サービスでは、ブロブストアの値を変換元として使用できます。ブロブストアの画像は、ブロブストア値の最大サイズと同じサイズまで許可されます。ただし、変換の結果はアプリケーションに直接返されるので、API 応答制限の 1 MB 以内である必要があります。これを利用して、ユーザーがアップロードした写真のサムネイル画像を作成できます。

Python の Blobstore の画像を変換するには、画像データを使用して Image コンストラクタの image_data 引数を設定する代わりに、blob_key 引数を値が画像の Blobstore キーに設定します。API のそれ以外の部分は予期したとおりに動作します。execute_transforms() メソッドは変換の結果を返します。結果が最大サイズである 1 MB を超える場合は、LargeImageError 例外を送出します。

Images Python API の概要 - Google App Engine — Google Developers

公式では、"blob_key"にブロブストアに保存されたパスを書けばおkよ〜
と書かれていましたが、どうも上手くいかない。

例では、最後にreturnされているので、
もしかするとダウンロードハンドラのかわりにThumbnailerクラスを入れるのでしょうか?
ううむ…