Panoramica dell'API Blobstore per i servizi in bundle legacy

L'API Blobstore consente alla tua applicazione di pubblicare 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, ad esempio 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 lo fanno presentando all'utente un modulo con un campo per il caricamento di file. Quando il modulo viene inviato, Blobstore crea un blob dai contenuti del file e restituisce un riferimento opaco al blob, chiamato chiave blob, che puoi utilizzare in un secondo momento per pubblicare il blob. L'applicazione può fornire il valore del blob completo in risposta alla richiesta di un utente oppure può leggere il valore direttamente utilizzando un'interfaccia simile a un file in modalità flusso.

Introduzione al Blobstore

Google App Engine include il servizio Blobstore, che consente alle applicazioni di gestire oggetti dati limitati solo dalla quantità di dati che possono essere caricati o scaricati tramite una singola connessione HTTP. Questi oggetti sono chiamati valori Blobstore o blob. I valori dell'archivio BLOB vengono pubblicati come risposte dai gestori delle richieste e creati come caricamenti tramite moduli web. Le applicazioni non creano direttamente i dati dei blob. vengono creati indirettamente, tramite un modulo web inviato o un'altra richiesta POST HTTP. I valori dell'archivio BLOB possono essere inviati all'utente o accessibili dall'applicazione in un flusso 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 per il caricamento di file. L'applicazione genera l'URL di azione del modulo chiamando l'API Blobstore. Il browser dell'utente carica il file direttamente in Blobstore tramite l'URL generato. Blobstore archivia quindi il blob, riscrive la richiesta in modo che contenga la chiave del blob e la passa a un percorso nell'applicazione. Un gestore di richieste in quel percorso della tua applicazione può eseguire ulteriori elaborazioni dei moduli.

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

I blob non possono essere modificati dopo la loro creazione, ma possono essere eliminati. Ogni BLOB ha un record di informazioni BLOB corrispondente, archiviato nel datastore, che fornisce dettagli sul blob, come l'ora di creazione e il tipo di contenuti. Puoi utilizzare la chiave del blob per recuperare i record di informazioni del blob ed eseguire query sulle relative proprietà.

Utilizzo di Blobstore

Le applicazioni possono utilizzare Blobstore per accettare file di grandi dimensioni come caricamenti da parte degli utenti e per pubblicarli. Una volta caricati, i file vengono chiamati BLOB. Le applicazioni non accedono ai blob direttamente dal nome file. Le applicazioni fanno invece riferimento ai BLOB tramite il tipo appengine.BlobKey.

L'utente crea un blob inviando un modulo HTML che include uno o più campi di input del file. La tua applicazione imposta blobstore.UploadURL come destinazione (azione) di questo modulo, passando alla funzione un percorso URL di un gestore nella tua applicazione. Quando l'utente invia il modulo, il browser dell'utente carica i file specificati direttamente in Blobstore. 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 un'elaborazione aggiuntiva in base alla chiave del blob. Infine, il gestore deve restituire una risposta di reindirizzamento solo intestazioni (301, 302 o 303), in genere un reindirizzamento del browser a un'altra pagina indicante lo stato del caricamento del blob.

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

Caricamento di un blob

Per creare e caricare un blob:

1. Crea un URL di caricamento

Richiama blobstore.UploadURL per creare un URL di caricamento per il modulo che l'utente compilerà, indicando il percorso di caricamento della richiesta una volta completato POST del modulo.

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

2. Creare un modulo di caricamento

Il modulo deve includere un campo per il caricamento di file e il valore enctype del modulo deve essere impostato su multipart/form-data. Quando l'utente invia il modulo, POST viene gestito dall'API Blobstore, che crea il blob. L'API crea anche un record di informazioni per il blob e lo archivia nel datastore, poi 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 del caricamento

In questo gestore, puoi memorizzare la chiave del blob con il resto del modello di dati dell'applicazione. La chiave del blob rimane accessibile dall'entità di informazioni del blob nel datastore. Tieni presente che, dopo che l'utente ha inviato il modulo e viene chiamato il tuo gestore, il blob è già stato salvato e le informazioni del blob sono state aggiunte al datastore. Se l'applicazione non vuole conservare il blob, devi eliminare il blob 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 l'archivio BLOB riscrive la richiesta dell'utente, il corpo delle parti MIME dei file caricati viene svuotato e la chiave BLOB viene aggiunta come intestazione della parte MIME. Tutti gli altri campi e parti del modulo vengono conservati e passati al gestore del caricamento. Se non specifichi un tipo di contenuto, l'archivio BLOB 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 nell'applicazione. Questo gestore deve passare la chiave del blob per il blob desiderato a blobstore.Send. In questo esempio, la chiave del blob viene passata al gestore del download come argomento URL r.FormValue("blobKey"). In pratica, il gestore dei download può ottenere la chiave blob con qualsiasi mezzo a tua scelta, ad esempio tramite un altro metodo o un'azione 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 del blob. App Engine sostituisce il corpo della risposta con il contenuto del blob.

Intervalli di byte dei blob

Blobstore supporta la pubblicazione di parte di un valore grande 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 relativo valore è un intervallo di byte HTTP standard. La numerazione di byte è in base zero. Un valore X-AppEngine-BlobRange vuoto indica all'API di ignorare l'intestazione dell'intervallo e pubblicare il blob completo. Ecco alcuni esempi di intervalli:

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

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

Blobstore non supporta più intervalli di 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 un file da caricare e il gestore del caricamento chiama immediatamente il gestore dei download per pubblicare i dati. Questo serve a semplificare l'applicazione di esempio. In pratica, probabilmente non useresti l'URL principale per richiedere i dati di caricamento né pubblicheresti immediatamente un blob che avevi 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 file nella sezione UploadURLOptions fornita alla funzione UploadURL. Nel gestore di caricamento, devi elaborare la mappa restituita dei BLOB restituiti e archiviare esplicitamente il nome file Google Cloud Storage necessario per recuperare il blob in un secondo momento.

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

Quote e limiti

Lo spazio utilizzato per i valori dell'archivio BLOB contribuisce ai Dati archiviati (fatturabili). quota. Le entità di informazioni sui blob nel datastore vengono conteggiate ai fini dei limiti relativi al datastore. Tieni presente che Google Cloud Storage è un servizio a pagamento; sarai in base alla definizione di Cloud Storage, Listino prezzi.

Per ulteriori informazioni sulle quote di sicurezza a livello di sistema, consulta Quote.

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

  • La dimensione massima dei dati di Blobstore che possono essere letti dall'applicazione con una chiamata API è di 32 megabyte.
  • Il numero massimo di file che possono essere caricati in un singolo post del modulo è 500.
Per informazioni su come aggirare questi limiti di dimensione, consulta la documentazione relativa alla funzione Invia.