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フォルダーにコピーします
名前が小文字のファイルなので、クリックすると表示されます
画像ファイルであれば内容を確認できます。
これで、プログラムの作成、実行、データベースの使用、ファイルの使用ができるようになりましたので、何かサンプルプログラムが作成できる状態になりました。