ファイル使用(deta.space Drive編)

deta.space - ファイル管理(Drive)

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後にクリックできません。

drive作成

deta.shでは、collectionsというくくりが無かったのですが、deta.spaceはcollectionsのなかに名前付きコレクションがありそれがbaseかdriveに分かれて、そのなかに実体があるようになっているので、階層が深くなっています。今回はdriveを選びます

drive作成

eventdriveというdriveコレクションの中にphotosという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フォルダーにコピーします

ファイル一覧

名前が小文字のファイルなので、クリックすると表示されます

画像表示

画像ファイルであれば内容を確認できます。

これで、プログラムの作成、実行、データベースの使用、ファイルの使用ができるようになりましたので、何かサンプルプログラムが作成できる状態になりました。