Panoramica dell'API Blobstore per i servizi in bundle legacy

L'API Blobstore consente all'applicazione di gestire oggetti di dati, chiamati blob,molto più grandi delle dimensioni consentite per gli oggetti nel servizio Datastore. I blob sono utili per pubblicare file di grandi dimensioni, come file video o immagine, e per consentire agli utenti di caricare file di dati di grandi dimensioni. I blob vengono creati caricando un file tramite una richiesta HTTP. In genere, le applicazioni eseguono questa operazione presentando all'utente un modulo con un campo per il caricamento di file. Quando il modulo viene inviato, il Blobstore crea un blob dai contenuti del file e restituisce un riferimento opaco al blob, chiamato chiave blob,che puoi utilizzare in seguito per pubblicare il blob. L'applicazione può fornire il valore completo del blob in risposta alla richiesta di un utente oppure può leggere il valore direttamente utilizzando un'interfaccia simile a un file di streaming.

Presentazione di Blobstore

Google App Engine include il servizio Blobstore, che consente alle applicazioni di gestire oggetti di dati limitati solo dalla quantità di dati che possono essere caricati o scaricati tramite una singola connessione HTTP. Questi oggetti sono chiamati valori dell'archivio BLOB o blob. I valori dell'archivio BLOB vengono pubblicati come risposte dai gestori delle richieste e vengono creati come caricamenti tramite moduli web. Le applicazioni non creano dati blob direttamente, ma vengono creati indirettamente tramite un modulo web inviato o un'altra richiesta POST HTTP. I valori dell'archivio BLOB possono essere forniti all'utente o accessibili dall'applicazione in uno stream simile a un file utilizzando l'API Blobstore.

Per richiedere a un utente di caricare un valore Blobstore, la tua applicazione presenta un modulo web con un campo di caricamento file. L'applicazione genera l'URL di azione del modulo chiamando l'API Blobstore. Il browser dell'utente carica il file direttamente nel Blobstore tramite l'URL generato. Il BLOB archivia quindi il blob, riscrive la richiesta in modo che contenga la chiave blob e la passa a un percorso nella tua applicazione. Un gestore delle richieste in quel percorso nella tua applicazione può eseguire un'elaborazione aggiuntiva del modulo.

Per gestire un blob, l'applicazione imposta un'intestazione sulla risposta in uscita e App Engine sostituisce la risposta con il valore del blob.

I blob non possono essere modificati dopo la creazione, ma possono essere eliminati. A ogni BLOB corrisponde un record di informazioni sul blob, memorizzato nel datastore, che fornisce dettagli sul blob, come l'ora di creazione e il tipo di contenuti. Puoi utilizzare la chiave blob per recuperare i record relativi alle informazioni sui blob ed eseguire query sulle loro proprietà.

Utilizzo del Blobstore

Le applicazioni possono utilizzare l'archivio BLOB per accettare file di grandi dimensioni come caricamenti degli utenti e per pubblicarli. Una volta caricati, i file vengono denominati blob. Le applicazioni non accedono ai blob direttamente in base al nome file. Le applicazioni fanno invece riferimento ai blob tramite il tipo appengine.BlobKey.

L'utente crea un blob inviando un modulo HTML che includa uno o più campi di immissione del file. L'applicazione imposta blobstore.UploadURL come destinazione (azione) di questo modulo, trasmettendo alla funzione un percorso URL di un gestore nella tua applicazione. Quando l'utente invia il modulo, il suo browser carica i file specificati direttamente nel Blobstore. Il Blobstore riscrive la richiesta dell'utente e archivia i dati del file caricato, sostituendo i dati del file caricato con una o più chiavi blob corrispondenti, quindi passa la richiesta riscritta al gestore nel percorso dell'URL che hai fornito a blobstore.UploadURL. Questo gestore può eseguire ulteriori elaborazioni in base alla chiave blob. Infine, il gestore deve restituire una risposta di reindirizzamento di sole intestazioni (301, 302 o 303), di solito un reindirizzamento del browser a un'altra pagina che indica lo stato del caricamento del blob.

L'applicazione può leggere parti di un valore dell'archivio BLOB utilizzando un blobstore.Reader.

Caricamento di un blob

Per creare e caricare un blob:

1. Crea un URL di caricamento

Chiama blobstore.UploadURL per creare un URL di caricamento per il modulo che l'utente compilerà, trasmettendo il percorso di richiesta da caricare al termine del POST del modulo.

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

2. Crea un modulo di caricamento

Il modulo deve includere un campo di caricamento file e il valore enctype del modulo deve essere impostato su multipart/form-data. Quando l'utente invia il modulo, il POST viene gestito dall'API Blobstore, che crea il blob. L'API crea inoltre un record di informazioni per il blob e lo archivia nel datastore, quindi passa la richiesta riscritta all'applicazione nel percorso specificato come chiave 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 il gestore dei caricamenti

In questo gestore puoi archiviare la chiave blob con il resto del modello dei dati della tua applicazione. La chiave blob stessa rimane accessibile dall'entità informazioni blob nel datastore. Tieni presente che, dopo che l'utente invia il modulo e viene chiamato il tuo gestore, il blob è già stato salvato e le informazioni sul blob sono state aggiunte al datastore. Se la tua applicazione non vuole conservare il blob, eliminalo immediatamente per evitare che diventi orfano:

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)

Quando il Blobstore riscrive la richiesta dell'utente, il corpo delle parti MIME dei file caricati viene svuotato e la chiave blob viene aggiunta come intestazione di parte MIME. Tutti gli altri campi e le altre parti del modulo vengono conservati e trasmessi al gestore dei caricamenti. Se non specifichi un tipo di contenuti, Blobstore proverà a deducerlo dall'estensione del file. Se non è possibile determinare il tipo di contenuto, al blob appena creato viene assegnato il tipo di contenuto application/octet-stream.

Pubblicazione di un blob

Per pubblicare i blob, devi includere un gestore del download dei blob come percorso nella tua applicazione. Questo gestore deve passare la chiave blob del blob desiderato a blobstore.Send. In questo esempio, la chiave blob viene passata al gestore dei download come argomento dell'URL r.FormValue("blobKey"). In pratica, il gestore dei download può ottenere la chiave blob con qualsiasi mezzo tu scelga, ad esempio tramite un altro metodo o un'altra azione dell'utente.

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

I blob possono essere pubblicati da qualsiasi URL dell'applicazione. Per pubblicare un blob nella tua applicazione, inserisci un'intestazione speciale nella risposta contenente la chiave blob. App Engine sostituisce il corpo della risposta con il contenuto del blob.

Intervalli di byte blob

Blobstore supporta la pubblicazione di parte di un valore di grandi dimensioni anziché del valore completo in risposta a una richiesta. Per pubblicare un valore parziale, includi l'intestazione X-AppEngine-BlobRange nella risposta in uscita. Il suo valore è un intervallo di byte HTTP standard. La numerazione dei byte è in base zero. Un X-AppEngine-BlobRange vuoto indica all'API di ignorare l'intestazione dell'intervallo e pubblicare il blob completo. Gli intervalli di esempio includono:

  • 0-499 gestisce i primi 500 byte del valore (byte da 0 a 499 inclusi).
  • 500-999 gestisce 500 byte a partire dal 501 byte.
  • 500- gestisce tutti i byte a partire dal 501° byte fino alla fine del valore.
  • -500 gestisce gli ultimi 500 byte del valore.

Se l'intervallo di byte è valido per il valore dell'archivio BLOB, quest'ultimo invia un codice di stato 206 Partial Content e l'intervallo di byte richiesto al client. Se l'intervallo non è valido per il valore, l'archivio BLOB invia 416 Requested Range Not Satisfiable.

L'archivio BLOB non supporta intervalli di più byte in una singola richiesta (ad esempio 100-199,200-299), indipendentemente dal fatto che si sovrappongano o meno.

Completa l'applicazione di esempio

Nella seguente applicazione di esempio, l'URL principale dell'applicazione carica il modulo che richiede all'utente il file da caricare e il gestore dei caricamenti chiama immediatamente il gestore dei download per fornire i dati. per semplificare l'applicazione di esempio. In pratica, probabilmente non useresti l'URL principale per richiedere i dati di caricamento, né pubblicheresti immediatamente un blob appena caricato.


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

Utilizzo dell'API Blobstore con Google Cloud Storage

Puoi utilizzare l'API Blobstore per archiviare i BLOB in Cloud Storage anziché in Blobstore. Devi configurare un bucket come descritto nella documentazione di Google Cloud Storage e specificare il bucket e il nome del file nel campo UploadURLOptions fornito per la funzione UploadURL. Nel gestore del caricamento, devi elaborare la mappa restituita dei blob restituiti e archiviare in modo esplicito il nome file di Google Cloud Storage necessario per recuperare il blob in un secondo momento.

Puoi anche gestire gli oggetti Cloud Storage utilizzando l'API Blobstore. Per gestire un oggetto Cloud Storage, usa BlobKeyForFile per generare il blobkey richiesto come descritto in Pubblicazione di un blob.

Quote e limiti

Lo spazio utilizzato per i valori del Blobstore contribuisce alla quota di dati archiviati (fatturabili). Le entità di informazione blob nel datastore vengono conteggiate ai fini dei limiti relativi al datastore. Google Cloud Storage è un servizio a pagamento, ti verrà addebitato in base al listino prezzi di Cloud Storage.

Per saperne di più sulle quote di sicurezza a livello di sistema, consulta Quote.

Oltre alle quote di sicurezza a livello di sistema, per l'utilizzo di Blobstore si applicano i seguenti limiti:

  • La dimensione massima dei dati dell'archivio BLOB che possono essere letti dall'applicazione con una chiamata API è di 32 megabyte.
  • Il numero massimo di file che possono essere caricati in un unico modulo POST è 500.
Per informazioni su come aggirare i limiti di dimensione, consulta la documentazione relativa alla funzione Send.