2008-09-17 29 views
76

Ich plane, eine Webanwendung zu erstellen, mit der Benutzer ihre Visual Studio-Projektdateien herunterstufen können. Es scheint jedoch, dass Google App Engine das Hochladen von Dateien und das Speichern von Dateien auf dem Google-Server über db.TextProperty und db.BlobProperty akzeptiert.Hochladen von Dateien in Google App Engine

Ich bin froh, dass jeder Code-Beispiel (sowohl die Client-und die Server-Seite) zur Verfügung stellen kann, wie dies getan werden kann.

+0

@ user858915 Der Link ist gebrochen :( – Marco

Antwort

41

Hier ist eine komplette, funktionierende Datei. Ich zog das Original von der Google-Website und änderte es, um es etwas mehr reale Welt zu machen.

ein paar Dinge zu bemerken:

  1. Dieser Code die BlobStore API
  2. Der Zweck dieser Linie in der ServeHandler-Klasse verwendet wird, zu „reparieren“ die Taste, so dass es von jeder loswird Name Mangeln, die in den Browser aufgetreten sein kann (ich beobachte nicht jeder in Chrome)

    blob_key = str(urllib.unquote(blob_key)) 
    
  3. Die "save_as" -Klausel am Ende ist wichtig. Es stellt sicher, dass der Dateiname nicht beschädigt wird, wenn er an Ihren Browser gesendet wird. Lass es los, um zu beobachten, was passiert.

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

Good Luck!

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 __name__ == '__main__': 
    main() 
+0

arbeitete für mich - danke – printminion

+0

Dies sollte die akzeptierte Antwort sein. – Brett

+0

Erstaunlich, dass dies für alle außer mir funktioniert ... 'selbst .__ uploads' in' blobstore_handler' ist 'None' wenn ich das versuche. – Tim

1

Sie können keine Dateien speichern, da es kein herkömmliches Dateisystem gibt. Sie können speichern sie nur in ihrem eigenen Datastor (in einem Feld als BlobProperty definiert)

Es gibt ein Beispiel in diesem Link:

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

obj = MyModel() 
obj.blob = db.Blob(file_contents) 
0

Es gibt keine Flat-Datei in Google App Engine zu speichern. Alles muss in die Datastore gehen, die ein bisschen wie eine relationale Datenbank ist, aber nicht ganz. Sie können die Dateien als TextProperty oder BlobProperty Attribute speichern.

Es gibt eine Grenze von 1 MB für DataStore-Einträge, die ein Problem darstellen können oder auch nicht.

+0

So speichern Sie Dateien größer als 1 MB. Ich verwende https://github.com/ckopanos/django-google-cloud-storage –

10

Es ist ein Thread in Google Groups darüber:

Uploading Files

Mit vielen nützlichen Code, dass die Diskussion hat mir geholfen, in dem Hochladen von Dateien sehr viel.

49

Tatsächlich wird diese Frage in der App Egnine-Dokumentation beantwortet. Ein Beispiel finden Sie unter Uploading User Images.

HTML-Code innerhalb <Form> </form >:

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

Python-Code:

class Guestbook(webapp.RequestHandler): 
    def post(self): 
    greeting = Greeting() 
    if 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('/')
+0

Nicht mögen diese Vorgehensweise Sie verursachen loser Mimetyp info – santiagobasulto

+0

@santiagobasulto: Warum überprüfen Sie es nicht selbst? – vietean

+0

Ich möchte es nicht überprüfen Wenn Sie ein Bild anzeigen müssen, müssen Sie Mime Type Info angeben (ob das Bild JPG, GIF usw.) Wenn Sie das Bild mit der von Ihnen bereitgestellten Lösung hochladen, wissen Sie in Zukunft nicht, welchen Inhaltstyp das Bild haben soll, also können Sie den Header nicht setzen , ergo, alt-ungerade Browser werden Probleme haben, das Bild anzuzeigen (wegen des Fehlens des Inhaltstyps) – santiagobasulto

3

Wenn Ihr immer noch ein Problem haben, versuchen Sie Sie enctype in dem Formular-Tag verwenden

Nr .:

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

Ja:

<form enctype="multipart/form-data" action="/upload"> 
+0

Ich habe einen Codierungsfehler erhalten, bevor ich Ihre Antwort implementiert habe –

+1

Ein wirklich nerviger Haken für mich, als ich dies tat, war nicht "Größe" für den Dateieingabetyp enthalten. Ich habe mit Safari getestet, das anscheinend eine sehr kurze Dateilänge hat (?) Und alles, was ich in GAE für den Inhalt der Datei bekommen habe, war der Dateiname. Nur ein Wort der Warnung, das jemandem kleinere Kopfschmerzen ersparen könnte. –

1

Persönlich fand ich das Tutorial beschrieben here nützlich, wenn die Java-Laufzeit mit GAE verwenden. Aus irgendeinem Grund, wenn ich eine Datei mit

<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> 

zu laden versucht, fand ich, dass meine HttpServlet Klasse aus irgendeinem Grund nicht die Form mit dem ‚enctype‘ Attribut akzeptieren würde. Das Entfernen funktioniert jedoch, das bedeutet, dass ich keine Dateien hochladen kann.

+1

Möglicherweise liegt es daran, dass Sie die get-Methode verwenden, versuchen Sie stattdessen, sie zu posten. Ich bin mir nicht sicher, ob es funktioniert, aber es ist einen Versuch wert. – slashnick

6

Google hat einen Dienst zum Speichern großer Dateien veröffentlicht. Schauen Sie sich blobstore API documentation an. Wenn Ihre Dateien> 1 MB groß sind, sollten Sie sie verwenden.

+0

So speichern Sie Dateien> 1 MB. Ich verwende github.com/ckopanos/django-google-cloud-storage –

6

ich es heute versuchen, Es funktioniert wie folgt:

meine sdk Version 1.3.x

HTML-Seite:

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

Server-Code:

file_contents = self.request.POST.get('myfile').file.read() 
+0

Funktioniert nicht für mich. –

0

I habe beim Hochladen von Dateien in App Engine ein merkwürdiges Verhalten beobachtet. Wenn Sie das folgende Formular aus:

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

Und dann extrahieren Sie die img aus der Anfrage wie folgt aus:

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

Die img_contents Variable ein str() in Google Chrome ist, aber es ist Unicode in Firefox. Und wie Sie jetzt, nimmt der db.Blob() Konstruktor eine Zeichenfolge und wird einen Fehler auslösen, wenn Sie eine Unicode-Zeichenfolge übergeben.

Weiß jemand, wie das behoben werden kann?

Auch was ich absolut seltsam finde ist, dass wenn ich die Gästebuch-Anwendung (mit Avataren) kopiere und einfüge, es perfekt funktioniert. Ich mache alles genau so in meinem Code, aber es wird einfach nicht funktionieren. Ich bin kurz davor, mir die Haare auszuziehen.

+2

: D Das Formular sagte: multiplart/form-data anstelle von multipart/form-data. Chrome ist schlau genug, um den Tippfehler zu korrigieren, Firefox ist es nicht. –

0

Es gibt einen Weg Flat-File-System der Verwendung von (Atleast in Nutzungsperspektive)

Es gibt diese Google App Engine Virtual FileSystem project. Dies wird mit Hilfe von Datenspeicher- und Memcache-APIs implementiert, um ein gewöhnliches Dateisystem zu emulieren. Mit dieser Bibliothek können Sie in Ihrem Projekt einen ähnlichen Dateisystemzugriff (Lesen und Schreiben) verwenden.