Descripción general de la API de Blobstore de Go

Nota: Debes considerar usar Google Cloud Storage en lugar de Blobstore para almacenar datos BLOB.

La API de Blobstore permite que tu aplicación entregue objetos de datos, llamados blobs, que son mucho más grandes que el tamaño permitido para los objetos en el servicio de Datastore. Los blobs son útiles para entregar archivos grandes, como archivos de video o imágenes, y para que los usuarios suban archivos de datos grandes. Los blobs se crean subiendo un archivo a través de una solicitud HTTP. Por lo general, para hacerlo tus aplicaciones presentarán un formulario con un campo de subida de archivos para el usuario. Cuando se envía el formulario, Blobstore crea un blob a partir del contenido del archivo y muestra una referencia opaca al blob, llamada clave de blob, que luego puede usar para entregar el blob. La aplicación puede entregar el valor completo del blob en respuesta a una solicitud del usuario, o puede leer el valor directamente mediante una interfaz similar a un archivo de transmisión.

Presentación de Blobstore

Google App Engine incluye el servicio Blobstore, que permite a las aplicaciones entregar objetos de datos limitados solo por la cantidad de datos que se pueden subir o descargar a través de una única conexión HTTP. Estos objetos se denominan valores de Blobstore, o blobs. Los valores de Blobstore se entregan como respuestas a la solicitud de los controladores y se crean como subidas a través de formularios web. Las aplicaciones no crean datos de blob directamente; en cambio, los blobs se crean indirectamente mediante un formulario web enviado o una solicitud POST de HTTP. Los valores de Blobstore se pueden entregar al usuario, o la aplicación puede acceder a ellos en una secuencia similar a un archivo, con la API de Blobstore.

Para solicitar 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 de Blobstore. El navegador del usuario sube el archivo directamente en Blobstore a través de la URL generada. Luego, Blobstore almacena el blob, vuelve a escribir la solicitud para que contenga la clave del blob y la pasa a una ruta en tu aplicación. Un controlador de solicitudes en esa ruta de tu aplicación puede realizar un procesamiento de formulario adicional.

Para entregar un blob, tu aplicación establece un encabezado en la respuesta saliente y App Engine reemplaza la respuesta con el valor de blob.

Los blobs no se pueden modificar después de que se crean, pero sí borrar. Cada blob tiene un registro de información de blob correspondiente, guardado en el almacén de datos, que proporciona detalles sobre el blob, como su hora de creación y tipo de contenido. Puedes usar la clave del BLOB para obtener registros de información de BLOB y consultar sus propiedades.

Cómo usar Blobstore

Las aplicaciones pueden usar Blobstore para aceptar archivos grandes, como subidas de usuarios, y entregar esos archivos. Una vez que se suben, los archivos se llaman BLOB. Las aplicaciones no acceden a los BLOB directamente por el nombre del archivo. En cambio, hacen referencia a los datos BLOB mediante el tipo appengine.BlobKey.

El usuario crea un BLOB mediante un formulario HTML que incluye uno o más campos de ingreso de archivos. Tu aplicación configura blobstore.UploadURL como el destino (acción) del formulario y le pasa a la función una ruta de URL de un controlador en la 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, almacena los datos del archivo subido y los reemplaza con una o más claves de BLOB correspondientes. A continuación, pasa la solicitud reescrita al controlador en la ruta de URL que proporcionaste a blobstore.UploadURL. Este controlador puede realizar un procesamiento adicional en función de la clave de BLOB. Finalmente, el controlador debe mostrar una respuesta de redireccionamiento de solo encabezados (301, 302 o 303), en general, un redireccionamiento del navegador hacia otra página que indica el estado de carga del BLOB.

La aplicación puede leer partes de un valor de Blobstore mediante un blobstore.Reader.

Cómo subir un BLOB

Para crear y subir un blob, sigue este procedimiento:

1. Crea una URL de carga

Llama a blobstore.UploadURL para crear una URL de carga correspondiente al formulario que el usuario llenará y pasar la ruta de la aplicación para cargar cuando se complete el POST del formulario.

ctx := appengine.NewContext(r)
uploadURL, err := blobstore.UploadURL(ctx, "/upload", nil)
if err != nil {
	serveError(ctx, w, err)
	return
}

2. Crea un formulario de subida

El formulario debe incluir un campo de subida de archivos, y el enctype del formulario debe establecerse en multipart/form-data. Cuando el usuario envía el formulario, el POST es controlado por la API de Blobstore, que crea un blob. También crea un registro de información para el BLOB, almacena el registro en el almacén de datos y pasa la solicitud reescrita a tu aplicación en la ruta dada como una clave de BLOB.

	var rootTemplate = template.Must(template.New("root").Parse(rootTemplateHTML))

	const rootTemplateHTML = `
<html><body>
<form action="{{.}}" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form></body></html>
`

3. Implementa un controlador de subida

En este controlador, puedes almacenar la clave de blob con el resto de tu modelo de datos de la aplicación. La clave de blob en sí permanece accesible desde la entidad de información de blob en el almacén de datos. Ten en cuenta que después de que el usuario envíe el formulario y se llame a tu controlador, el blob ya estará guardado y la información agregada al almacén de datos. Si tu aplicación no quiere mantener el BLOB, debes borrarlo de inmediato para evitar que quede suelto:

ctx := appengine.NewContext(r)
blobs, _, err := blobstore.ParseUpload(r)
if err != nil {
	serveError(ctx, w, err)
	return
}
file := blobs["file"]
if len(file) == 0 {
	log.Errorf(ctx, "no file uploaded")
	http.Redirect(w, r, "/", http.StatusFound)
	return
}
http.Redirect(w, r, "/serve/?blobKey="+string(file[0].BlobKey), http.StatusFound)

Cuando Blobstore reescribe la solicitud del usuario, se vacían los cuerpos de las partes MIME de los archivos subidos y se agrega la clave BLOB como parte del encabezado MIME. Todos los demás campos de formulario y las partes se conservan y se pasan al controlador de subida. Si no especificas un tipo de contenido, Blobstore intentará inferirlo de la extensión del archivo. Si no se puede determinar ningún tipo de contenido, al blob recién creado se le asigna el tipo de contenido application/octet-stream.

Cómo entregar un BLOB

Para entregar los BLOB, debes incluir un controlador de descarga de BLOB como una ruta en tu aplicación. Este controlador debe pasar la clave de BLOB del BLOB deseado a blobstore.Send. En este ejemplo, la clave de BLOB se pasa al controlador de descarga como el argumento de la URL r.FormValue("blobKey"). En la práctica, el controlador de descarga puede obtener la clave BLOB por cualquier medio que elijas, por ejemplo, a través de otro método o acción del usuario.

blobstore.Send(w, appengine.BlobKey(r.FormValue("blobKey")))

Pueden entregarse los BLOB desde cualquier URL de la aplicación. Para entregar un BLOB en tu aplicación, colocas un encabezado especial en la respuesta que contiene la clave de BLOB. App Engine reemplaza el cuerpo de la respuesta con el contenido del blob.

Rangos de bytes de blob

Blobstore admite el servicio de parte de un valor grande en lugar del valor total en respuesta a una solicitud. Para entregar un valor parcial, incluye el encabezado X-AppEngine-BlobRange en la respuesta saliente. Su valor es un rango de byte HTTP estándar. La numeración de bytes está basada en cero. Un X-AppEngine-BlobRange en blanco indica a la API que ignore el encabezado del rango y entregue el blob completo. Los rangos de ejemplo incluyen lo siguiente:

  • 0-499 entrega los primeros 500 bytes del valor (bytes 0 a 499, incluido).
  • 500-999 entrega 500 bytes comenzando con el byte 501.
  • 500- entrega todos los bytes que comienzan con el byte 501 hasta final del valor.
  • -500 entrega los últimos 500 bytes del valor.

Si el rango de byte es válido para el valor de Blobstore, este envía un código de estado 206 Partial Content y un rango de byte solicitado al cliente. Si el rango no es válido para el valor, Blobstore envía 416 Requested Range Not Satisfiable.

Blobstore no admite varios rangos de bytes en una sola solicitud (por ejemplo, 100-199,200-299), ya sea que se superpongan o no.

Aplicación de muestra completa

En la siguiente aplicación de muestra, la URL principal de la aplicación sube el formulario que solicita al usuario que suba un archivo, y el controlador de subida llama inmediatamente al controlador de descarga para que entregue los datos. Esto es para simplificar la aplicación de muestra. En la práctica, probablemente no usarías la URL principal para solicitar datos de carga, ni tampoco entregarías de inmediato un BLOB que acabas de subir.


package blobstore_example

import (
	"context"
	"html/template"
	"io"
	"net/http"

	"google.golang.org/appengine"
	"google.golang.org/appengine/blobstore"
	"google.golang.org/appengine/log"
)

func serveError(ctx context.Context, w http.ResponseWriter, err error) {
	w.WriteHeader(http.StatusInternalServerError)
	w.Header().Set("Content-Type", "text/plain")
	io.WriteString(w, "Internal Server Error")
	log.Errorf(ctx, "%v", err)
}

var rootTemplate = template.Must(template.New("root").Parse(rootTemplateHTML))

const rootTemplateHTML = `
<html><body>
<form action="{{.}}" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form></body></html>
`

func handleRoot(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	uploadURL, err := blobstore.UploadURL(ctx, "/upload", nil)
	if err != nil {
		serveError(ctx, w, err)
		return
	}
	w.Header().Set("Content-Type", "text/html")
	err = rootTemplate.Execute(w, uploadURL)
	if err != nil {
		log.Errorf(ctx, "%v", err)
	}
}

func handleServe(w http.ResponseWriter, r *http.Request) {
	blobstore.Send(w, appengine.BlobKey(r.FormValue("blobKey")))
}

func handleUpload(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	blobs, _, err := blobstore.ParseUpload(r)
	if err != nil {
		serveError(ctx, w, err)
		return
	}
	file := blobs["file"]
	if len(file) == 0 {
		log.Errorf(ctx, "no file uploaded")
		http.Redirect(w, r, "/", http.StatusFound)
		return
	}
	http.Redirect(w, r, "/serve/?blobKey="+string(file[0].BlobKey), http.StatusFound)
}

func init() {
	http.HandleFunc("/", handleRoot)
	http.HandleFunc("/serve/", handleServe)
	http.HandleFunc("/upload", handleUpload)
}

Cómo usar la API de Blobstore con Google Cloud Storage

Puedes usar la API de Blobstore para almacenar BLOB en Cloud Storage en lugar de almacenarlos en Blobstore. Debes configurar un depósito, como se describe en la documentación de Google Cloud Storage, y especificar el depósito y el nombre de archivo en UploadURLOptions que proporcionas para la función UploadURL. En tu controlador de carga, debes procesar el mapa de los BLOB que se muestran y almacenar de forma explícita en Google Cloud Storage el nombre de archivo necesario para recuperar el BLOB más tarde.

También puedes entregar objetos de Cloud Storage con la API de Blobstore. Si deseas entregar un objeto de Cloud Storage, usa BlobKeyForFile para generar la blobkey necesaria, como se describe en Entrega un BLOB.

Cuotas y límites

El espacio usado por los valores de Blobstore contribuyen a la cuota Datos almacenados (facturable). Las entidades de información de blob en el almacén de datos cuentan con los límites relacionados con el almacén de datos. Ten en cuenta que Google Cloud Storage es un servicio de pago por uso; se te cobrará de acuerdo con la hoja de precios de Cloud Storage.

Para obtener más información sobre las cuotas de seguridad en todo el sistema, consulte Cuotas.

Además de las cuotas de seguridad para todo el sistema, los límites siguientes se aplican específicamente al uso de Blobstore:

  • 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.
  • La cantidad máxima de archivos que pueden subirse en un solo formulario POST es de 500.
Para obtener más información sobre cómo trabajar con estos límites de tamaño, consulta la documentación sobre la función Send.
¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Entorno estándar de App Engine para Go