1

我需要創建GAE使用下列程序:如何保存上傳的文件,然後用GAE返回?

  1. 用戶上傳一些文件(假設POST,要myapp.appspot.com/upload);
  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() 

它是正確的嗎?該方法是否正確?或者,我不應該使用數據存儲?

Upd。奇怪,但下面的代碼

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+)不抓住每一個base64,以url applications_-編碼的關鍵是有效的字符,你應該與他們以及像這樣的東西/file/([\w_-]+)

+0

Cron作業與任何其他離線任務具有相同的10分鐘時間限制 - 10分鐘。不過,用ETA排隊單個任務刪除每個blob將是一個更好的解決方案。 –

+0

@尼克哦,很高興知道,我沒有意識到它的感謝。我一直認爲cron-jobs調用是面向用戶的請求。關於評論的第二部分,你的意思是比使用mapper-api更好? – systempuntoout

+0

Mapreduce適用於批量更新,但在此我們確切知道哪些記錄需要更新。每個記錄排隊一個任務,刪除該記錄,很簡單,應該可以正常工作。 –

3

從粗略的代碼看,你的方法應該可以工作。但是,您可能想要使用Blobstore而不是數據存儲區中的斑點,具體取決於您嘗試提供的文件的需求和大小。

+0

什麼是Blob存儲使用情況的優勢在哪裏?文件是~20Kb。 –

+0

如果您的文件是20kb,那麼請堅持使用數據存儲。以下是blobstore vs數據存儲的簡要概述。 blobstore的優點:1)您可以存儲更大的文件;數據存儲實體每個都限制爲1MB。 2)便宜; blobstore配額大約比高複製數據存儲便宜3倍。但是,缺點:1)您必須啓用計費;你可以獲得1GB的免費空間,但是你的應用程序必須讓它能夠使用blobstore。 2)Blobstore不支持命名空間。 –

+0

名稱空間或多或少與blobstore無關,因爲它會發出不透明的密鑰 - 只要確保將密鑰存儲在相關名稱空間中的數據存儲實體中即可。 –

相關問題