先日のブログエントリに書きましたが、GAE Uploaderをいじっていて制限にぶち当たりました。
- アップロードは10MBまで
- Datastoreのレコードは1MBまで
アップロードしたファイルをDatastoreに保存しようとすると、
アップロード可能サイズ > 保存可能サイズ
なので、そのまま保存することが出来ません。
対策として、アップロードファイルをchunkに分割してDatastoreに並び順付きで保存すればいいらしい。で、実際にコードを書いてみたら動いたので、オリジナルのGAE Uploaderからの差分を公開。
[code lang=“python”] — main.py-orig 2009-04-04 18:59:58.000000000 +0900 +++ main.py 2009-04-04 20:46:38.000000000 +0900 @@ -16,6 +16,7 @@ comment = db.StringProperty() size = db.IntegerProperty() author = db.UserProperty() + split = db.IntegerProperty(0) created_at = db.DateTimeProperty(auto_now_add=True)
def delete(self):
@@ -27,6 +28,7 @@ class FileBin(db.Model): userfile = db.ReferenceProperty(UserFile) bin = db.BlobProperty() + sortorder = db.IntegerProperty()
class MainPage(webapp.RequestHandler):
def get(self):
@@ -50,14 +52,21 @@
if not userfile:
self.error(404)
return self.response.out.write(‘404 not found’)
- bin = userfile.filebin_set.get()
if isinstance(self.request.get(‘dl’), unicode):
self.response.headers[‘Content-Type’] = ‘application/octet-stream’
content_disposition = ‘attachment; filename=“%s”’ % str(userfile.name) # header values must be string.
self.response.headers[‘Content-Disposition’] = content_disposition
else:
- self.response.headers[‘Content-Type’] = str(userfile.mime)
- self.response.out.write(bin.bin)
+ self.response.headers[‘Content-Type’] = str(userfile.mime)
+
+ if userfile.split == 1:
+ results = userfile.filebin_set.order(‘sortorder’).fetch(10)
+
+ for result in results:
+ self.response.out.write(result.bin)
+ else:
+ bin = userfile.filebin_set.get()
+ self.response.out.write(bin.bin)
class Upload(webapp.RequestHandler): def post(self): @@ -71,9 +80,22 @@ userfile.comment = self.request.get(“comment”) bin = db.Blob(file_data) userfile.size = len(bin) + if len(bin) > 1000000: + userfile.split=1 + userfile.put() - filebin = FileBin(userfile=userfile, bin=bin) - filebin.put() + + if len(file_data) > 1000000: + for i in range(0, 9): + chunk = file_data[i1000000:i1000000+1000000] + filebin=FileBin(userfile=userfile, bin=chunk, sortorder=i) + filebin.put() + if len(chunk) < 1000000: + break + else: + filebin = FileBin(userfile=userfile, bin=bin) + filebin.put() + # delete oldest file if UserFile.all().count() > FILE_MAX: oldest_file = UserFile.all().order(‘created_at’).get() [/code] ※マジックナンバーが埋まってるのはご愛敬で
とりあえず正常に動いているみたい?
pythonはまだまだ駆け出しでよく解らないところがある。 例えば、
- substr()ってないの?
- Blob objectってどうやって連結するの?(stringみたいに+したら駄目でした)
などなど。
GAE Uploaderは自分のレベルにマッチした良い教材でした。公開してくださったid:ikasamaHさんに感謝。
[ad#text_wide]