Pregunta

Estoy planeando crear una aplicación web que permita a los usuarios degradar los archivos de sus proyectos de Visual Studio.Sin embargo, parece que Google App Engine acepta la carga de archivos y el almacenamiento de archivos planos en el servidor de Google a través de db.TextProperty y db.BlobProperty.

Estaré encantado de que alguien pueda proporcionar un ejemplo de código (tanto del lado del cliente como del servidor) sobre cómo se puede hacer esto.

¿Fue útil?

Solución

Aquí hay un archivo de trabajo completo.Saqué el original del sitio de Google y lo modifiqué para hacerlo un poco más real.

Algunas cosas a tener en cuenta:

  1. Este código utiliza el API de tienda de blobs
  2. El propósito de esta línea en la clase ServHandler es "arreglar" la clave para que elimine cualquier nombre que pueda haber ocurrido en el navegador (no observé ninguno en Chrome)

    blob_key = str(urllib.unquote(blob_key))
    
  3. La cláusula "save_as" al final de esto es importante.Se asegurará de que el nombre del archivo no se altere cuando se envíe a su navegador.Deshazte de él para observar lo que sucede.

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

¡Buena suerte!

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

Otros consejos

De hecho, esta pregunta se responde en la documentación de App Egnine.Vea un ejemplo en Cargar imágenes de usuario.

Código HTML, dentro de <formulario></form>:

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

Código 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('/')

Hay un hilo en Grupos de Google al respecto:

Subiendo archivos

Con mucho código útil, esa discusión me ayudó mucho a subir archivos.

Google ha lanzado un servicio para almacenar archivos de gran tamaño.Mira esto Documentación de la API del almacén de blobs.Si tus archivos pesan > 1 MB, deberías usarlo.

Lo pruebo hoy, funciona de la siguiente manera:

mi versión SDK es 1.3.x

página html:

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

Código del servidor:

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

Si aún tienes problemas, verifica que estés usando enctype en la etiqueta del formulario.

No:

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

Sí:

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

No puede almacenar archivos ya que no existe un sistema de archivos tradicional.Sólo puedes almacenarlos en su propio DataStore (en un campo definido como Propiedad Blob)

Hay un ejemplo en el enlace anterior:

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

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

Personalmente encontré el tutorial descrito. aquí útil cuando se utiliza el tiempo de ejecución de Java con GAE.Por alguna razón, cuando intenté cargar un archivo 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>

Descubrí que mi clase HttpServlet, por alguna razón, no aceptaba el formulario con el atributo 'enctype'.Eliminarlo funciona, sin embargo, esto significa que no puedo cargar ningún archivo.

No hay almacenamiento de archivos planos en Google App Engine.Todo tiene que entrar en el Almacén de datos que es un poco como una base de datos relacional pero no del todo.

Podrías almacenar los archivos como Propiedad de texto o Propiedad Blob atributos.

Hay un límite de 1 MB en las entradas del DataStore, lo que puede ser un problema o no.

He observado un comportamiento extraño al cargar archivos en App Engine.Al enviar el siguiente formulario:

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

Y luego extraes el img de la solicitud como esta:

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

El img_contents variable es una str() en Google Chrome, pero es Unicode en Firefox.Y como usted ahora, el db.Blob() El constructor toma una cadena y arrojará un error si pasa una cadena Unicode.

¿Alguien sabe cómo se puede solucionar esto?

Además, lo que me parece absolutamente extraño es que cuando copio y pego la aplicación Libro de visitas (con avatares), funciona perfectamente.Hago todo exactamente de la misma manera en mi código, pero simplemente no funciona.Estoy muy cerca de arrancarme el pelo.

Hay una manera de usar sistema de archivos planos(Al menos en la perspectiva de uso)

hay esto Proyecto de sistema de archivos virtual de Google App Engine.que se implementa con la ayuda de las API de almacén de datos y Memcache para emular un sistema de archivos normal.Usando esta biblioteca puedes usar en tu proyecto un acceso similar al sistema de archivos (lectura y escritura).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top