web-dev-qa-db-fra.com

Importer des fichiers dans Google App Engine

Je prévois de créer une application Web qui permet aux utilisateurs de rétrograder leurs fichiers de projet Visual Studio. Cependant, il semble que Google App Engine accepte le téléchargement de fichiers et le stockage de fichiers plats sur le serveur Google via db.TextProperty et db.BlobProperty.

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

77
Graviton

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

Quelques points à noter:

  1. Ce code utilise BlobStore API
  2. Le but de cette ligne dans la classe ServeHandler est de "corriger" la clé afin qu'elle se débarrasse de toute altération de nom qui aurait pu se produire dans le navigateur (je n'en ai pas observé 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 modifié lorsqu'il est envoyé à votre navigateur. Débarrassez-vous-en 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 __== '__main__':
  main()
42
010110110101

En fait, cette question trouve sa réponse dans la documentation App Egnine. Voir un exemple sur Téléchargement d'images utilisateur .

Code HTML, à l'intérieur de <form> </form>:

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

Code Python:

livre d'or de classe (webapp.RequestHandler): 
 def post (self): 
 greeting = Greeting () 
 if users.get_current_user (): 
 salutation.author = users.get_current_user () 
 salutation.content = self.request.get ("contenu") 
 avatar = self.request.get ("img") 
 salutation.avatar = db.Blob (avatar) 
 salutation.put () 
 self.redirect ('/')
49
sastanin

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

Téléchargement de fichiers

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

10
Gustavo Diaz Jaimes

Je l'essaie aujourd'hui, cela 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() 
6
Bili

Google a publié un service de stockage de fichiers volumineux. Jetez un œil à documentation de l'API blobstore . Si vos fichiers sont> 1 Mo, vous devez l'utiliser.

6
jbochi

Si vous rencontrez toujours un problème, vérifiez que vous utilisez enctype dans la balise de formulaire

Non:

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

Oui:

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

Vous ne pouvez pas stocker de fichiers car il n’existe pas de système de fichiers traditionnel. Vous ne pouvez les stocker que 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 )
1
Guido

Personnellement, j'ai trouvé le tutoriel décrit ici utile lors de l'utilisation de Java run time avec GAE. Pour une raison quelconque, lorsque 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>

J'ai trouvé que ma classe HttpServlet pour une raison quelconque n'acceptait pas le formulaire avec l'attribut 'enctype'. Le supprimer fonctionne, cependant, cela signifie que je ne peux pas télécharger de fichiers.

1
Vijay Sharma

Il existe un moyen d'utiliser un système de fichiers plat (au moins dans une perspective d'utilisation)

Il y a ceci projet de système de fichiers virtuel Google App Engine . qui est implémenté à l'aide d'API de banque de données et de memcache pour émuler un système de fichiers ordinaire. En utilisant cette bibliothèque, vous pouvez utiliser pour projeter un accès au système de fichiers similaire (lecture et écriture) .

0
vivek_jonam

Aucun fichier plat n'est stocké dans Google App Engine. Tout doit aller dans le Datastore qui est un peu comme une base de données relationnelle mais pas tout à fait.

Vous pouvez stocker les fichiers en tant qu'attributs TextProperty ou BlobProperty .

Il existe une limite de 1 Mo sur les entrées DataStore qui peut ou non être un problème.

0
Dave Webb

J'ai 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 requête comme ceci:

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

La variable img_contents Est une str() dans Google Chrome, mais c'est unicode dans Firefox. Et comme vous le faites maintenant, le constructeur db.Blob() prend une chaîne et générera une erreur si vous passez une chaîne unicode.

Quelqu'un sait-il comment résoudre ce problème?

De plus, ce que je trouve absolument étrange, c'est que lorsque je copie et colle l'application du livre d'or (avec des avatars), cela fonctionne parfaitement. Je fais tout exactement de la même manière dans mon code, mais cela ne fonctionnera tout simplement pas. Je suis sur le point d'arracher mes cheveux.

0
Honza Pokorny