Sube archivos al almacenamiento en la nube de Google desde la aplicación appengine

Estoy seguro de que la respuesta a esta pregunta es fácil, pero para mí se ha demostrado que es muy frustrante ya que no puedo poner ninguna solución que haya encontrado en un código práctico para mi propio uso.

Estoy creando una aplicación en el motor de la aplicación que permite al usuario cargar un archivo, que luego la aplicación actúa. El tamaño del archivo suele ser de unos pocos Mbs, y en algunos casos hasta unos 20 Mb aproximadamente. Esto es suficiente para activar el tiempo de espera de 30 segundos en el motor de la aplicación y, por lo tanto, estoy intentando cargar en el almacenamiento en la nube directamente como se sugiere en varios sitios web (incluido aquí).

La parte de subir de mi formulario se ve así:

    

Y el manejador se ve así (solo estoy empezando con el motor de la aplicación, así que pido disculpas si esto parece estúpido).

 class TransformPage(BaseHandler): def get(self): self.render_template('transform.html',name=self.request.get('form')) def post(self): filename = self.request.POST['coords'].filename filesize = int(self.request.headers['Content_Length']) if filesize>5242880: self.redirect('/error') else: save_to_cloud(file.value,filename) # Start processing file here 

Puse el cheque por el tamaño del archivo como una forma muy simple de prevenir el tiempo de espera de los 30, y 5Mb parece ser el tamaño máximo que puedo pasar en 30 en mi red.

Save_to_cloud () es solo una envoltura que escribí sobre la API de almacenamiento en la nube de Google, y se parece a esto:

 def save_to_cloud(f,filename): filename = BUCKET + filename create_file_and_write(f,filename) 

Lo de arriba funciona y veo que los archivos cargados terminan en el almacenamiento en la nube, pero como dije anteriormente, se descompone para archivos más grandes. He visto sugerencias sobre el uso de create_upload_url en la búsqueda, pero no soy lo suficientemente bueno para ver cómo se relaciona con mi caso, en particular para que los contenidos del archivo cargado se lean en la memoria para poder escribirlos en el almacenamiento en la nube.

Esta es probablemente la cosa más fácil del mundo si sabes cómo se hace, pero no puedo hacerlo sin que alguien me muestre en código cómo se puede hacer 🙁

Gracias

Edit: @Itamar: esto es lo que estoy tratando de lograr, aunque el formulario de carga también contiene algunas otras selecciones que debe realizar el usuario. Ahora he cambiado mi código a este

 class TransformPage(BaseHandler): def get(self): upload_url =blobstore.create_upload_url('/upload',gs_bucket_name='/my_bucket/') self.render_template('transform.html', {'name':self.request.get('form'), {'upload_url':upload_url}) 

Pero no puedo hacer que upload_url aparezca en la plantilla html que se ve así.

  

Si entiendo correctamente, lo que intentas hacer es entregar un formulario de App Engine que permita a un usuario elegir un archivo para cargar. Dado que el archivo cargado puede ser grande, no desea manejar la carga en App Engine, sino que el archivo se cargue directamente en Google Cloud Storage.

Esto se puede hacer, y no es demasiado difícil. De hecho, este es exactamente el ejemplo dado en los documentos de App Engine Python Blobstore . Puede ser confuso que el ejemplo se refiera a Blobstore mientras desea el archivo en Cloud Storage, pero está bien, parece que desde la versión 1.7.0 puede hacer esto:

 upload_url = blobstore.create_upload_url('/upload', gs_bucket_name='my_bucket') 

(en lugar del paso 1 en el ejemplo que vinculé), y la URL de carga se cargará directamente a Cloud Storage.

Ahora, su acción de formulario debe ser la cadena upload_url que fue devuelta por la función blobstore.create_upload_url .

Una vez que el formulario complete el procesamiento (lo que significa que el archivo se ha cargado), se redirigirá al argumento que se pasó a esa función (en el ejemplo, a /upload ).

No es necesario que escriba su propia función de procesamiento POST, como se describe en la pregunta.

He creado una idea general que muestra cómo cargar y usar archivos GCS: https://gist.github.com/voscausa/9541133

Este es el código para manejar la publicación de formulario multiparte:

 class GcsUpload(webapp2.RequestHandler): def post(self): field_storage = self.request.POST.get("file", None) if isinstance(field_storage, cgi.FieldStorage): file_name = field_storage.filename dyn = gcs_data.Dynamics(id=file_name, filename=file_name) gcs_file_name = gcs_data.gcs_write_blob(dyn, field_storage.file.read()) gcs_data.gcs_serving_url(dyn) dyn.put() logging.info('Uploaded and saved in default GCS bucket : ' + gcs_file_name) self.response.headers[b'Content-Type'] = gcs_data.gcs_content_type(dyn) self.response.write(gcs_data.gcs_read_blob(dyn)) else: logging.error('GCS Upload failed')