deta.spaceでファイルを扱う
deta.spaceでprojectを使うとき、テンポラリーファイルを作ろうとするとエラーになってしまいます。マニュアルをみると/tmpにしかデータが作れない、read only systemとなっています。
しかし、サービスの一つにDriveがあり、ここにファイルを入れられるようなので作ってみます。
Driveにフォルダーを作る
deta.shでは、最初のdriveの作成はMicroで行いあとはGUIでできました。deta.spaceでは最初からGUIで作成できます。ただしマニュアルには書いてありませんが、1ファイル当たりのサイズは4Mbyte程度までにしないとTOO LARGEやInternal Errorになります。また拡張子は小文字でないと、upload後にクリックできません。
deta.shでは、collectionsというくくりが無かったのですが、deta.spaceはcollectionsのなかに名前付きコレクションがありそれがbaseかdriveに分かれて、そのなかに実体があるようになっているので、階層が深くなっています。今回はdriveを選びます
eventdriveというdriveコレクションの中にphotosというdriveを作ります
Microと同じ方法でspace newでproject用のフォルダーを作り、そこにプログラムを入力して、実行します。フォルダー内のファイルを全部消してしまうと、自動的にフォルダーも消滅します。実行方法はcanvasでアイコンをクリックしてください。
ファイルをuploadするプログラムを作る
では、ファイルをuploadするサンプルを作ってみましょう。
main.py
from flask import Flask, request, make_response, jsonify from deta import Deta import os import string import random from PIL import Image #install Pillow from PIL.ExifTags import TAGS # 関数の定義 01 def get_exif_of_image(file): """Get EXIF of an image if exists. 指定した画像のEXIFデータを取り出す関数 @return exif_table Exif データを格納した辞書 """ im = Image.open(file) # Exif データを取得 # 存在しなければそのまま終了 空の辞書を返す try: exif = im._getexif() except AttributeError: return {} # タグIDそのままでは人が読めないのでデコードして # テーブルに格納する exif_table = {} for tag_id, value in exif.items(): tag = TAGS.get(tag_id, tag_id) exif_table[tag] = str(value) #データーで保存するとエラーが起きることがあるのでstr() return exif_table def randStr(leng): s = '' for i in range(leng): s += random.choice(string.digits + string.ascii_letters) return s app = Flask(__name__) #drive接続 deta = Deta("data keyを入れる") photos = deta.Drive("photos") @app.route('/') def index(): return """ <form action="/upload" enctype="multipart/form-data" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="10000"> <input name="file" type="file" accept="image/*"> <input type="submit"> </form> """ @app.route('/upload',methods=['POST']) def upload_img(): filedata = request.files['file'] f = filedata.filename #実ファイル名 tmpfilename = randStr(10) #temporaryファイル名 request.files['file'].save('/tmp/' + tmpfilename) #一旦/tmp別名で保存する length = os.stat('/tmp/'+ tmpfilename).st_size #ファイルサイズを調べる tmpfile = open('/tmp/'+tmpfilename,'rb') #imageファイルの中身を読み込む tmpdata = tmpfile.read() res = photos.put( f,tmpdata ) #Driveに保存する tmpfile.close() #imageファイルを閉じる exif = get_exif_of_image('/tmp/'+tmpfilename) #exifで撮影日付を取得する os.remove('/tmp/'+tmpfilename) #imageファイルを消す return make_response(jsonify({'result':res,'size':length,'tmpfile':tmpfilename,'datetime':exif['DateTime']}))
reqirements.txt
deta flask Pillow
実行すると、まずファイル選択画面になりますので、適当な4MByte以下のファイルを選択して、送信してください。
最初はデータは空っぽです
minato.jpgという114k byteの小さなファイルを送信します
写真のexifファイルを読み込み撮影日時を取得して表示、その後photosフォルダーにコピーします
名前が小文字のファイルなので、クリックすると表示されます
画像ファイルであれば内容を確認できます。
これで、プログラムの作成、実行、データベースの使用、ファイルの使用ができるようになりましたので、何かサンプルプログラムが作成できる状態になりました。