2008-09-17 7 views
76

Je prévois de créer une application Web permettant aux utilisateurs de rétrograder leurs fichiers de projet de studio visuel. Toutefois, il semble que Google App Engine accepte les téléchargements de fichiers et le stockage de fichiers plats sur le serveur Google via les numéros db.TextProperty et db.BlobProperty.Importer des fichiers dans Google App Engine

Je serais heureux que tout le monde puisse fournir un exemple de code (côté client et serveur) sur la façon dont cela peut être fait.

+0

@ user858915 Le lien est cassé :( – Marco

Répondre

41

Voici un fichier de travail complet. J'ai tiré l'original du site Google et l'ai modifié pour le rendre un peu plus réel.

Quelques choses à noter:

  1. Ce code utilise le BlobStore API
  2. Le but de cette ligne dans la classe de ServeHandler est de « réparer » la clé pour qu'il se débarrasse de tout le nom mangling qui ont pu se produire dans le navigateur (je ne ai vu aucun dans Chrome)

    blob_key = str(urllib.unquote(blob_key)) 
    
  3. La clause "save_as" à la fin de ceci est importante. Il s'assurera que le nom du fichier ne soit pas tronqué lorsqu'il est envoyé à votre navigateur. Débarrassez-vous pour observer ce qui se passe.

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

Bonne chance!

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

travaillé pour moi - merci – printminion

+0

Cela devrait être la réponse acceptée. – Brett

+0

Incroyable que cela fonctionne pour tout le monde sauf pour moi ... 'self .__ uploads' dans' blobstore_handler' est 'None' quand j'essaye ceci. – Tim

1

Vous ne pouvez pas stocker de fichiers car il n'existe pas de système de fichiers traditionnel. Vous ne pouvez les stocker dans leur propre DataStore (dans un champ défini comme BlobProperty)

Il y a un exemple dans le lien précédent:

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

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

Il n'y a pas de fichier plat stocker dans Google App Engine. Tout doit aller à la Datastore qui est un peu comme une base de données relationnelle mais pas tout à fait.

Vous pouvez sauvegarder les fichiers en tant que attributs TextProperty ou BlobProperty.

Il existe une limite de 1 Mo sur les entrées du stock de données, ce qui peut poser problème ou non.

+0

Comment enregistrer des fichiers supérieurs à 1 Mo. J'utilise https://github.com/ckopanos/django-google-cloud-storage –

10

Il y a un fil dans Google Groupes à ce sujet:

Uploading Files

Avec beaucoup de code utile, cette discussion m'a beaucoup aidé dans le téléchargement de fichiers.

49

En fait, cette question est traitée dans la documentation App Egnine. Voir un exemple sur Uploading User Images.

code HTML, à l'intérieur <forme> </form >:

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

code Python:

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

N'aime pas cette approche parce que vous – santiagobasulto

+0

@santiagobasulto: Pourquoi ne pas le vérifier par nous-mêmes? – vietean

+0

Je ne veux pas le vérifier Lorsque vous devez afficher une image, vous devez fournir des informations de type mime (que l'image soit JPG, GIF) Si vous téléchargez l'image avec la solution que vous fournissez, vous ne saurez pas à l'avenir le type de contenu de la photo, ergo, vous ne pouvez pas définir l'en-tête. , ergo, les anciens navigateurs bizarres auront des problèmes pour afficher l'image (en raison de l'absence du type de contenu) – santiagobasulto

3

Si votre avoir encore un problème, vérifiez que vous utilisez enctype dans la balise form

No:

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

Oui:

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

Je recevais une erreur d'encodage avant que j'implémente votre réponse –

+1

Un hic réel ennuyeux pour moi quand je faisais ceci n'incluait pas "taille" pour le type d'entrée de dossier. Je testais avec Safari qui a apparemment une longueur de fichier très courte par défaut (?) Et tout ce que j'obtenais dans GAE pour le contenu du fichier était le nom du fichier. Juste un mot d'avertissement qui pourrait sauver quelqu'un d'un mal de tête mineur. –

1

Personnellement, je trouve le tutoriel décrit here utile lors de l'utilisation du temps Java exécuté avec GAE. Pour une raison quelconque, quand j'ai essayé de télécharger un fichier en utilisant

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

Je trouve que ma classe HttpServlet pour une raison quelconque n'accepterait pas la forme avec l'attribut « enctype ». La suppression fonctionne, cependant, cela signifie que je ne peux pas télécharger de fichiers.

+1

Il se peut que ce soit parce que vous utilisez la méthode get, essayez plutôt de le publier. Je ne sais pas si ça va marcher mais ça vaut la peine d'essayer. – slashnick

6

Google a lancé un service de stockage de fichiers volumineux. Jetez un oeil à blobstore API documentation. Si vos fichiers sont> 1 Mo, vous devriez l'utiliser.

+0

Comment enregistrer des fichiers> 1mb. J'utilise github.com/ckopanos/django-google-cloud-storage –

6

J'essaie aujourd'hui, il fonctionne comme suit:

ma version sdk est 1.3.x

page html:

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

Code Serveur:

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

Ne fonctionne pas pour moi. –

0

I avez observé un comportement étrange lors du téléchargement de fichiers sur App Engine. Lorsque vous soumettez le formulaire suivant:

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

Et puis vous extrayez le img de la demande comme ceci:

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

La variable img_contents est un str() dans Google Chrome, mais il est unicode dans Firefox. Et comme vous maintenant, le constructeur db.Blob() prend une chaîne et lancera une erreur si vous passez dans une chaîne unicode.

Est-ce que quelqu'un sait comment cela peut être réparé?

Aussi, ce que je trouve absolument étrange est que lorsque je copie et colle l'application Guestbook (avec des avatars), cela fonctionne parfaitement. Je fais tout exactement la même chose dans mon code, mais ça ne marchera pas. Je suis très proche de me tirer les cheveux.

+2

: D Le formulaire dit: mutlipart/form-data au lieu de multipart/form-data. Chrome est assez intelligent pour corriger la faute de frappe, Firefox ne l'est pas. –

0

Il y a une façon d'utiliser système de fichier plat (Atleast en perspective d'utilisation)

Il y a cette Google App Engine Virtual FileSystem project. qui est implémenté à l'aide des API de datastore et memcache pour émuler un système de fichiers ordinaire. En utilisant cette bibliothèque, vous pouvez utiliser dans votre projet un accès au système de fichiers similaire (lecture et écriture).

Questions connexes