La API Blobstore permite que tu aplicación sirva objetos de datos, llamados blobs,que son mucho más grandes que el tamaño permitido para los objetos del servicio Datastore. Los blobs son útiles para servir archivos grandes, como archivos de vídeo o de imagen, y para permitir que los usuarios suban archivos de datos grandes. Los blobs se crean subiendo un archivo mediante una solicitud HTTP. Normalmente, las aplicaciones lo hacen mostrando un formulario con un campo de subida de archivos al usuario. Cuando se envía el formulario, Blobstore crea un blob a partir del contenido del archivo y devuelve una referencia opaca al blob, llamada clave de blob,que puedes usar más adelante para servir el blob. La aplicación puede proporcionar el valor completo del blob en respuesta a una solicitud del usuario o leer el valor directamente mediante una interfaz de streaming similar a un archivo.
Introducción al almacén de blob
App Engine incluye el servicio Blobstore, que permite a las aplicaciones servir objetos de datos limitados únicamente por la cantidad de datos que se pueden subir o descargar a través de una sola conexión HTTP. Estos objetos se denominan valores de Blobstore o blobs.
Los valores de Blobstore se proporcionan como respuestas de los controladores de solicitudes y se crean como subidas a través de formularios web. Las aplicaciones no crean datos de blob directamente, sino que los blobs se crean de forma indirecta mediante un formulario web enviado u otra solicitud HTTP POST.
Los valores de Blobstore se pueden servir al usuario o la aplicación puede acceder a ellos en un flujo similar a un archivo mediante la API Blobstore.
Para pedir a un usuario que suba un valor de Blobstore, tu aplicación presenta un formulario web con un campo de subida de archivos. La aplicación genera la URL de acción del formulario llamando a la API Blobstore. El navegador del usuario sube el archivo directamente a Blobstore a través de la URL generada. A continuación, Blobstore almacena el blob, reescribe la solicitud para que contenga la clave del blob y la envía a una ruta de tu aplicación. Un controlador de solicitudes en esa ruta de tu aplicación puede realizar un procesamiento adicional del formulario.
Para servir un blob, tu aplicación define un encabezado en la respuesta saliente y App Engine sustituye la respuesta por el valor del blob.
Los blobs no se pueden modificar una vez creados, pero sí se pueden eliminar. Cada blob tiene un registro de información de blob correspondiente, almacenado en el almacén de datos, que proporciona detalles sobre el blob, como la hora de creación y el tipo de contenido. Puede usar la clave de blob para obtener registros de información de blob y consultar sus propiedades.
Una aplicación puede leer un valor de Blobstore por partes mediante una llamada a la API.
Cada parte puede tener el tamaño máximo permitido de un valor devuelto por el API.
Este tamaño es un poco inferior a 32 megabytes, que se representa
en Python mediante la
constante google.appengine.ext.blobstore.MAX_BLOB_FETCH_SIZE
.
Una aplicación no puede crear ni modificar valores de Blobstore, excepto a través de archivos que haya subido el usuario.
Uso del almacén de blob
Las aplicaciones pueden usar Blobstore para aceptar archivos grandes que los usuarios suban y para ofrecer esos archivos. Los archivos se denominan blobs una vez que se han subido. Las aplicaciones no acceden a los blobs directamente.En su lugar, las aplicaciones trabajan con blobs mediante entidades de información de blob (representadas por la clase
BlobInfo
) en Datastore.
El usuario crea un blob enviando un formulario HTML que incluye uno o varios campos de entrada de archivos. Tu aplicación
llamadas
blobstore.create_upload_url()
para obtener
el destino (acción) de este formulario, pasando a la función
una ruta de URL de un controlador en tu aplicación. Cuando el usuario envía el formulario,
el navegador del usuario sube los archivos especificados directamente a Blobstore. Blobstore
reescribe la solicitud del usuario y almacena los datos del archivo subido, sustituyendo
los datos del archivo subido por una o varias claves de blob correspondientes y, a continuación, pasa la
solicitud reescrita al controlador en la ruta de URL que has proporcionado a
blobstore.create_upload_url()
.
Este controlador puede llevar a cabo procesos adicionales de acuerdo con la clave de blob.
La aplicación puede leer partes de un valor de Blobstore mediante una
Interfaz de streaming similar a un archivo. Consulta la clase BlobReader.
Subir un blob
Para crear y subir un blob, sigue este procedimiento:
1. Crear una URL de subida
Llama a
blobstore.create_upload_url()
para crear una URL de subida del formulario que rellenará el usuario.
Pasa la ruta de la aplicación que se cargará cuando se complete el POST del formulario.
Hay una versión asíncrona, create_upload_url_async(). Permite que el código de aplicación siga ejecutándose mientras Blobstore genera la URL de subida.
2. Crear un formulario de subida
El formulario debe incluir un campo de subida de archivos y el enctype del formulario debe ser multipart/form-data. Cuando el usuario envía el formulario, la API Blobstore gestiona el POST, que crea el blob. La API también crea un registro de información del blob, lo almacena en Datastore y envía la solicitud reescrita a tu aplicación en la ruta indicada como clave de blob.
Debes servir la página del formulario con un Content-Type de text/html; charset=utf-8, o se interpretarán mal los nombres de archivo que contengan caracteres no ASCII.
Como Blobstore para Python 3 no usa webapp, debes definir tu propio Content-Type para evitar que tu framework web defina un tipo de contenido predeterminado y que App Engine lo defina como un tipo estimado.
No puedes usar un balanceador de carga de aplicaciones externo global con un NEG sin servidor para gestionar las solicitudes de subida enviadas a la URL /_ah/upload/ devuelta por la llamada blobstore.create_upload_url.
En su lugar, debe dirigir esas solicitudes de subida directamente al servicio de App Engine. Para ello, puedes usar el dominio appspot.com o un dominio personalizado asignado directamente al servicio de App Engine.
3. Implementar un controlador de subida
En este controlador, puedes almacenar la clave del blob con el resto del modelo de datos de tu aplicación. La clave del blob sigue siendo accesible desde la entidad de información del blob en Datastore. Ten en cuenta que, después de que el usuario envíe el formulario y se llame a tu controlador, el blob ya se habrá guardado y la información del blob se habrá añadido a Datastore. Si tu aplicación no quiere conservar el blob, debes eliminarlo inmediatamente para evitar que quede huérfano.
En todas las aplicaciones Flask, todas las llamadas realizadas a métodos de la claseBlobstoreUploadHandler
requieren request.environ dictionary (solicitud importada del módulo
flask). Si tu aplicación es una aplicación WSGI sin un framework web, debes usar el parámetro environ en el método get_uploads().
Cuando se reescribe la solicitud del usuario, Blobstore vacía las partes MIME de los archivos subidos y añade la clave de blob como encabezado de parte MIME. Blobstore
conserva todos los demás campos y partes del formulario y los transfiere al controlador de subida.
Si no especifica un tipo de contenido, Blobstore intentará deducirlo a partir de la extensión del archivo. Si no puede determinar un tipo de contenido, asigna el tipo de contenido application/octet-stream al blob recién creado.
Servir un blob
Para servir blobs, debes incluir un controlador de descarga de blobs como una ruta en tu aplicación.
La aplicación sirve un blob configurando un encabezado en la respuesta saliente. Si usas Flask, la clase BlobstoreDownloadHandler requiere el diccionario request.environ (la solicitud se importa del módulo flask). Si tu aplicación es una aplicación WSGI sin un framework web, debes usar el parámetro environ en los métodos send_blob()
.
Los blobs se pueden servir desde cualquier URL de aplicación. Para servir un blob en tu aplicación, debes incluir un encabezado especial en la respuesta que contenga la clave del blob. App Engine sustituye el cuerpo de la respuesta por el contenido del blob.
Intervalos de bytes de blobs
Blobstore admite el servicio de una parte de un valor grande en lugar del valor completo
en respuesta a una solicitud. Para servir un valor parcial, incluya el encabezado X-AppEngine-BlobRange
en la respuesta saliente. Su valor es un intervalo de bytes HTTP estándar. La numeración de bytes se basa en cero. Un X-AppEngine-BlobRange
indica a la API que ignore el encabezado Range y que sirva el blob completo.
Entre los ejemplos de intervalos se incluye:
0-499sirve los primeros 500 bytes del valor (bytes del 0 al 499, ambos incluidos).500-999sirve 500 bytes a partir del byte 501.500-sirve todos los bytes a partir del byte 501 hasta el final del valor.-500sirve los últimos 500 bytes del valor.
Si el intervalo de bytes es válido para el valor de Blobstore, Blobstore envía un código de estado 206 Partial Content y el intervalo de bytes solicitado al cliente. Si el intervalo no es válido para el valor, Blobstore envía 416 Requested Range Not Satisfiable.
Blobstore no admite varios intervalos de bytes en una sola solicitud (por ejemplo, 100-199,200-299), tanto si se solapan como si no.
Aplicación de ejemplo completa
Consulta el ejemplo de aplicación Flask en la guía de la API Blobstore para Python 3.
Usar el servicio Imágenes con Blobstore
El servicio de imágenes puede utilizar un valor del almacén de blob como fuente de una transformación. La imagen original puede tener el tamaño máximo permitido para un valor del almacén de blob. El servicio Imágenes sigue devolviendo la imagen transformada a la aplicación, por lo que la imagen transformada debe tener un tamaño inferior a 32 megabytes. Esto resulta útil para crear imágenes en miniatura de fotografías grandes que suben los usuarios. Para obtener información sobre cómo usar el servicio Imágenes con valores de Blobstore, consulta la Documentación del servicio de imágenes
Usar la API Blobstore con Cloud Storage
Puedes usar la API Blobstore para almacenar blobs en Cloud Storage en lugar de almacenarlos en Blobstore. Debes configurar un segmento tal como se describe en la documentación de Cloud Storage y especificar el segmento y el nombre de archivo en
blobstore.create_upload_url gs_bucket_name.
En el controlador de subida, debes procesar los metadatos de metadatos de FileInfo y almacenar explícitamente el nombre de archivo de Cloud Storage necesario para recuperar el blob más adelante.
También puedes servir objetos de Cloud Storage mediante la API Blobstore.
Si quieres una solución de almacenamiento de objetos más moderna, te recomendamos que migres de Blobstore de App Engine a Cloud Storage.
Usar BlobReader
Una aplicación puede leer datos de valores de Blobstore mediante una interfaz similar a un objeto file de Python. Esta interfaz puede empezar a leer un valor en cualquier posición de byte y usa varias llamadas de servicio y almacenamiento en búfer, por lo que una aplicación puede acceder al tamaño completo del valor a pesar del límite de tamaño de una sola respuesta de llamada de servicio.
La clase BlobReader
puede tomar uno de estos tres valores como argumento de su constructor:
El objeto implementa los métodos de archivo conocidos para leer el valor. La aplicación no puede modificar el valor de Blobstore; los métodos de archivo para escribir no se han implementado.
Crear solicitudes asíncronas
Una aplicación puede llamar a algunas funciones de Blobstore que funcionan en segundo plano.
Blobstore lleva a cabo la solicitud mientras la aplicación hace otras cosas. Para hacer la solicitud, la aplicación llama a una función asíncrona. La función devuelve inmediatamente un objeto RPC, que representa la solicitud. Cuando la aplicación necesita el resultado de la solicitud, llama al método get_result() del objeto RPC.
Si el servicio no ha completado la solicitud cuando la aplicación llama a get_result(), el método espera hasta que se complete la solicitud (o hasta que se haya alcanzado la fecha límite o se haya producido un error). El método devuelve el objeto de resultado o genera una excepción si se ha producido un error al llevar a cabo la solicitud. Por ejemplo, este fragmento de código
upload_url = blobstore.create_upload_url('/upload')
slow_operation()
self.response.out.write("""<form action="%s" method="POST"
enctype="multipart/form-data">""" % upload_url)
se convierte en
upload_url_rpc = blobstore.create_upload_url_async('/upload')
slow_operation()
upload_url = upload_url_rpc.get_result()
self.response.out.write("""<form action="%s" method="POST"
enctype="multipart/form-data">""" % upload_url)
En este ejemplo, la aplicación ejecuta el código slow_operation() al mismo tiempo que Blobstore genera la URL de subida.
Cuotas y límites
El espacio usado para los valores de Blobstore se incluye en la cuota de datos almacenados (facturables). Las entidades de información de blobs de Datastore se tienen en cuenta para los límites relacionados con Datastore. Ten en cuenta que Cloud Storage es un servicio de pago por uso, por lo que se te cobrará según la hoja de precios de Cloud Storage.
Para obtener más información sobre las cuotas de seguridad de todo el sistema, consulta Cuotas.
Además de las cuotas de seguridad de todo el sistema, se aplican los siguientes límites específicamente al uso del almacén de blobs:
- El tamaño máximo de los datos de Blobstore que puede leer la aplicación con una llamada a la API es de 32 megabytes.
- El número máximo de archivos que se pueden subir en una sola publicación de formulario es de 500.