1

私はGAEの使用状況で、次のアプリケーションを作成する必要があります。アップロードしたファイルを保存してGAEでそれを返す方法は?

  1. ユーザー(のはmyapp.appspot.com/uploadするPOSTを言わせて)いくつかのファイルをアップロードします。
  2. 私はそれを(データストア内に)保存してリンクを返す必要があります。
  3. 提供されたリンクに基づいて、ユーザーは次の5分以内にファイルをダウンロードできるはずです。

    app.yamlを

    application: synoext 
    version: 1 
    runtime: python 
    api_version: 1 
    
    handlers: 
    - url: /upload 
        script: synoext.py 
    
    - url: /file/\w+ 
        script: synoext.py 
    
    - url: /cleanup 
        script: synoext.py 
    

    synoext.py

    import datetime 
    import logging 
    import urlparse 
    
    from google.appengine.ext import webapp 
    from google.appengine.ext.webapp.util import run_wsgi_app 
    from google.appengine.ext import db 
    from google.appengine.api import urlfetch 
    
    class Files(db.Model): 
        file = db.BlobProperty() 
        added = db.DateTimeProperty(auto_now_add=True) 
    
    class UploadFile(webapp.RequestHandler): 
        def post(self): 
         logging.info('(POST) Uploading new file') 
         # saving file in the database 
         file = Files() 
         file.file = db.Blob(self.request.get("file")) 
         file.put() 
    
         self.response.out.write('http://myapp.appspot.com/' + str(file.key())) 
    
    class GetFile(webapp.RequestHandler): 
        def get(self, key): 
         file = db.get(key) 
         if file is not None: 
          self.response.headers['Content-Type'] = 'application/x-bittorrent' 
          self.response.out.write(file.file) 
         else: 
          self.response.set_status(404) 
    
    class Cleanup(webapp.RequestHandler): 
        def get(self): 
         '''Automatically run job (cron) to delete old records (maximum 10000) 
         from Files database (records, which are older than 5 minutes) 
         ''' 
         fiveMinutesAgoDate = datetime.datetime.now() - datetime.timedelta(minutes=5) 
    
         q = db.GqlQuery("SELECT * FROM Files WHERE added < :1", fiveMinutesAgoDate) 
         results = q.fetch(10000) 
         db.delete(results) 
    
         self.response.out.write('{"result": true}') 
    
    
    application = webapp.WSGIApplication(
                [('/upload', UploadFile), 
                 ('/file/(\w+)', GetFile), 
                 ('/cleanup', Cleanup)], 
                debug=True) 
    
    def main(): 
        run_wsgi_app(application) 
    
    if __name__ == "__main__": 
        main() 
    

    それは正しいです:

私は次のように作成しましたか?アプローチは正しいですか?または、データストアを使用しないでください。

更新。奇妙ですが、次のコード

def get(self, key): 
    file = db.get(key) 
    if file is not None: 

正しくないキーを使用すると正しく動作しません。 ここで何が間違っていますか?

答えて

1

保存されているファイルはかなり小さいので、間違いなく正確にdatastoreに行ってください。

ヒント:

  1. あなただけ削除するキーを必要とするので、あなたはSELECT __key__ FROM Files WHERE ..は、いくつかのリソースを節約して、単にキーを照会する必要があります。

  2. ファイルの数が膨大な場合は、mapper-apiを使用してすべてのエントリを削除できます。 control apiを使用してコードからmapreduceジョブを開始することができます。

  3. /file/(\w+)url applications_-ごとにbase64でエンコードされたキーをキャッチしていない有効な文字であり、あなたはブロブストアの使用の利点は何この/file/([\w_-]+)

+0

Cronジョブの時間制限は、他のオフラインタスクと同じ10分です.10分です。ただし、個々のタスクをETAでエンキューして各BLOBを削除することは、より良い解決策になります。 –

+0

@ニックオハイオ州知っておいて、私は感謝を知らなかった。私はいつも、cron-jobsがユーザーに面会していると思っていました。コメントの2番目の部分に関しては、mapper-apiを使用するよりも優れていますか? – systempuntoout

+0

Mapreduceは一括更新には適していますが、ここではどのレコードを更新する必要があるか正確に分かります。そのレコードだけを削除するレコードごとに1つのタスクをエンキューするのは簡単で、うまくいくはずです。 –

3

コードを見渡すと、あなたのアプローチはうまくいくはずです。ただし、データストア内のブロブの代わりにBlobstoreを使用することができます。これは、必要とするファイルのサイズに応じて行います。

+0

ようなもので、同様にそれらを一致させる必要がありますか?ファイルは〜20Kbです。 –

+0

ファイルが20kbの場合は、データストアを使用してください。ここでは、blobstoreとデータストアの概要を簡単に説明します。ブロブストアの賛否両論:1)はるかに大きなファイルを保存することができます。データストアのエンティティはそれぞれ1MBに制限されています。 2)安いです。ブロブストアのクォータは、高レプリケーションデータストアの約3倍です。しかし、短所:1)請求を有効にする必要があります。あなたは1GBの空き容量がありますが、あなたのアプリはblobstoreを使用できるようにする必要があります。 2)Blobstoreは名前空間をサポートしていません。 –

+0

名前空間は、不透明なキーを発行するので、ブロブストアとは関係がありません。関連する名前空間のデータストアエンティティにキーを格納するようにしてください。 –

関連する問題