1

내가 GAE 사용 다음과 같은 응용 프로그램을 만들어야합니다업로드 된 파일을 저장 한 다음 GAE로 반환하는 방법은 무엇입니까?

  1. 사용자가 어떤 파일을 업로드 (의 그 myapp.appspot.com/upload에 POST를 가정 해 봅시다)
  2. 데이터 저장소에 저장하고 링크를 반환해야합니다.
  3. 제공된 링크를 기반으로 사용자는 다음 5 분 이내에 파일을 다운로드 할 수 있어야합니다.

    애플리케이션 제목을

    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+) 유효한 문자이며, 당신이 그들을 일치뿐만 아니라와 Blob 저장소 사용의 장점은 무엇이 /file/([\w_-]+)

+0

크론 작업의 작업 시간은 다른 오프라인 작업과 동일한 10 분 - 10 분입니다. ETA를 사용하여 개별 작업을 큐에 넣으면 각 BLOB를 삭제할 수 있습니다. –

+0

@ 닉 오, 잘 알았어. 나는 그 덕택을 몰랐다. 나는 항상 cron-jobs이 사용자 대면 요청이라고 생각했다. 의견의 두 번째 부분에 대해서는 매퍼 - API를 사용하는 것보다 낫지 않습니까? – systempuntoout

+0

Mapreduce는 일괄 업데이트에 적합하지만 업데이트 할 레코드가 무엇인지 정확히 알고 있습니다. 해당 레코드를 삭제하는 레코드 당 하나의 작업을 큐에 넣는 것은 간단하며 정상적으로 작동해야합니다. –

3

코드를 자세히 살펴보면 접근 방법이 효과적입니다. 그러나 사용자가 필요로하는 파일 크기에 따라 데이터 저장소에 BLOB 대신 Blobstore을 사용할 수 있습니다.

+0

같은해야 모든 64 기수에게 url applications, _-에 대한 암호화 키를 잡을하지 않는 이유는 무엇입니까? 파일은 ~ 20Kb입니다. –

+0

파일이 20kb라면 데이터 저장소를 사용하십시오. 다음은 blobstore와 datastore의 간단한 개요입니다. blobstore의 장점 : 1) 훨씬 큰 파일을 저장할 수 있습니다. 데이터 저장소 엔티티는 각각 1MB로 제한됩니다. 2) 저렴합니다. BLOBstore 할당량은 고 복제 데이터 스토어보다 약 3 배 저렴합니다. 그러나 단점 : 1) 결제 기능을 사용하도록 설정해야합니다. 1GB는 무료이지만 앱에서 BLOB 스토어를 사용하도록 설정해야합니다. 2) Blobstore는 네임 스페이스를 지원하지 않습니다. –

+0

네임 스페이스는 불투명 한 키를 발행하기 때문에 브로 쓰 스토어와 관련성이 없으므로 관련 네임 스페이스의 데이터 스토어 엔티티에 키를 저장하십시오. –

관련 문제