it-swarm.it

Carica file in Google App Engine

Sto progettando di creare un'app Web che consenta agli utenti di eseguire il downgrade dei file di progetto di Visual Studio. Tuttavia, sembra che Google App Engine accetti il ​​caricamento di file e l'archiviazione di file flat sul server di Google tramite db.TextProperty e db.BlobProperty.

Sarò felice che chiunque possa fornire un esempio di codice (sia client che lato server) su come eseguire questa operazione.

77
Graviton

Ecco un file completo e funzionante. Ho estratto l'originale dal sito di Google e l'ho modificato per renderlo leggermente più reale.

Alcune cose da notare:

  1. Questo codice utilizza BlobStore API
  2. Lo scopo di questa linea nella classe ServeHandler è di "correggere" la chiave in modo che si sbarazzi di qualsiasi nome che potrebbe essersi verificato nel browser (non ne ho osservato nessuno in Chrome)

    blob_key = str(urllib.unquote(blob_key))
    
  3. La clausola "save_as" alla fine di questo è importante. Si assicurerà che il nome del file non venga alterato quando viene inviato al tuo browser. Sbarazzati di esso per osservare cosa succede.

    self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
    

In bocca al lupo!

import os
import urllib

from google.appengine.ext import blobstore
from google.appengine.ext import webapp
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app

class MainHandler(webapp.RequestHandler):
    def get(self):
        upload_url = blobstore.create_upload_url('/upload')
        self.response.out.write('<html><body>')
        self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
        self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit" name="submit" value="Submit"> </form></body></html>""")

        for b in blobstore.BlobInfo.all():
            self.response.out.write('<li><a href="/serve/%s' % str(b.key()) + '">' + str(b.filename) + '</a>')

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files = self.get_uploads('file')
        blob_info = upload_files[0]
        self.redirect('/')

class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, blob_key):
        blob_key = str(urllib.unquote(blob_key))
        if not blobstore.get(blob_key):
            self.error(404)
        else:
            self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)

def main():
    application = webapp.WSGIApplication(
          [('/', MainHandler),
           ('/upload', UploadHandler),
           ('/serve/([^/]+)?', ServeHandler),
          ], debug=True)
    run_wsgi_app(application)

if __== '__main__':
  main()
42
010110110101

In effetti, a questa domanda viene data risposta nella documentazione di App Egnine. Vedi un esempio su Caricamento delle immagini dell'utente .

Codice HTML, all'interno di <form> </form>:

<input type = "file" name = "img" />

Codice Python:

guestbook di classe (webapp.RequestHandler): 
 def post (self): 
 greeting = Greeting () 
 se users.get_current_user (): 
 greeting.author = users.get_current_user () 
 greeting.content = self.request.get ("content") 
 avatar = self.request.get ("img") 
 greeting.avatar = db.Blob (avatar) 
 greeting.put () 
 self.redirect ('/')
49
sastanin

C'è una discussione in Google Gruppi al riguardo:

Caricamento dei file

Con molto codice utile, quella discussione mi ha aiutato moltissimo nel caricamento dei file.

10

Lo provo oggi, funziona come segue:

la mia versione di sdk è la 1.3.x.

pagina HTML:

<form enctype="multipart/form-data" action="/upload" method="post" > 
<input type="file" name="myfile" /> 
<input type="submit" /> 
</form> 

Codice server:

file_contents = self.request.POST.get('myfile').file.read() 
6
Bili

Google ha rilasciato un servizio per l'archiviazione di file di grandi dimensioni. Dai un'occhiata a documentazione API blobstore . Se i tuoi file sono> 1 MB, dovresti usarli.

6
jbochi

Se il problema persiste, controlla di utilizzare enctype nel tag del modulo

No:

<form encoding="multipart/form-data" action="/upload">

Sì:

<form enctype="multipart/form-data" action="/upload">
3
Joe Petrini

Non è possibile archiviare i file in quanto non esiste un file system tradizionale. Puoi memorizzarli solo nel loro DataStore (in un campo definito come BlobProperty )

C'è un esempio nel link precedente:

class MyModel(db.Model):
  blob = db.BlobProperty()

obj = MyModel()
obj.blob = db.Blob( file_contents )
1
Guido

Personalmente ho trovato il tutorial descritto qui utile quando ho usato Java tempo di esecuzione con GAE. Per qualche ragione, quando ho provato a caricare un file usando

<form action="/testservelet" method="get" enctype="multipart/form-data">
    <div>
        Myfile:<input type="file" name="file" size="50"/>
    </div>

    <div>
        <input type="submit" value="Upload file">
    </div>
</form>

Ho scoperto che la mia classe HttpServlet per qualche motivo non avrebbe accettato il modulo con l'attributo 'enctype'. Rimuoverlo funziona, tuttavia, ciò significa che non riesco a caricare alcun file.

1
Vijay Sharma

C'è un modo di usare file system flat (Atleast nella prospettiva di utilizzo)

Esiste questo progetto Virtual FileSystem di Google App Engine . implementato con l'aiuto di API datastore e memcache per emulare un normale filesystem. Usando questa libreria puoi usare nel tuo progetto un accesso al filesystem simile (lettura e scrittura) .

0
vivek_jonam

Non è possibile archiviare file flat in Google App Engine. Tutto deve andare nel Datastore che è un po 'come un database relazionale ma non del tutto.

È possibile archiviare i file come TextProperty o BlobProperty attributi.

Esiste un limite di 1 MB per le voci del DataStore che può essere o meno un problema.

0
Dave Webb

Ho osservato alcuni comportamenti strani durante il caricamento di file su App Engine. Quando invii il seguente modulo:

<form method="post" action="/upload" enctype="multipart/form-data">
    <input type="file" name="img" />
    ...
</form>

E quindi estrai img dalla richiesta in questo modo:

img_contents = self.request.get('img')

La variabile img_contents È una str() in Google Chrome, ma è unicode in Firefox. E come ora, il costruttore db.Blob() accetta una stringa e genererà un errore se passi una stringa unicode.

Qualcuno sa come risolvere questo problema?

Inoltre, ciò che trovo assolutamente strano è che quando copio e incollo l'applicazione Guestbook (con avatar), funziona perfettamente. Faccio tutto esattamente allo stesso modo nel mio codice, ma semplicemente non funzionerà. Sono molto vicino a togliermi i capelli.

0
Honza Pokorny