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, 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 tue applicazioni eseguono questa operazione presentando all'utente un modulo con un campo di caricamento 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 potrai utilizzare in un secondo momento per pubblicare il blob. L'applicazione può fornire il valore completo del blob in risposta a una richiesta dell'utente oppure può leggere il valore direttamente utilizzando un'interfaccia simile a un file in streaming.

Introduzione all'archivio BLOB

App Engine include il servizio Blobstore, che consente alle applicazioni di pubblicare oggetti di dati limitati solo dalla quantità di dati che possono essere caricati o scaricati su 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 vengono creati come caricamenti tramite moduli web. Le applicazioni non creano direttamente i dati dei blob, ma indirettamente tramite un modulo web inviato o un'altra richiesta HTTP POST. I valori di Blobstore possono essere inviati all'utente o essere accessibili dall'applicazione in un stream simile a un file utilizzando l'API Blobstore.

Per chiedere 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 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 delle richieste in quel percorso dell'applicazione può eseguire un'ulteriore elaborazione del modulo.

Per pubblicare un blob, l'applicazione imposta un'intestazione nella 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 sul BLOB corrispondente, archiviato nel datastore, che fornisce dettagli sul BLOB, ad esempio la data 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à.

Un'applicazione può leggere un valore Blobstore una parte alla volta utilizzando una chiamata API. La dimensione della parte può essere pari alla dimensione massima di un valore restituito dall'API. Questa dimensione è leggermente inferiore a 32 megabyte, rappresentata in Python dalla costante google.appengine.ext.blobstore.MAX_BLOB_FETCH_SIZE. Un'applicazione non può creare o modificare i valori di Blobstore, tranne tramite i file caricati dall'utente.

Utilizzo di Blobstore

Le applicazioni possono utilizzare Blobstore per accettare file di grandi dimensioni come caricamenti da parte degli utenti e per pubblicarli. I file vengono chiamati blob dopo il caricamento. Le applicazioni non accedono direttamente ai blob, ma lavorano con i BLOB tramite le entità di informazioni sui BLOB (rappresentate dalla BlobInfo classe) in Datastore.

L'utente crea un blob inviando un modulo HTML che includa uno o più campi di immissione file. La tua applicazione chiama blobstore.create_upload_url() per ottenere la destinazione (azione) di questo modulo, passando alla funzione un percorso URL di un gestore nell'applicazione. Quando l'utente invia il modulo, il browser dell'utente carica i file specificati direttamente in 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.create_upload_url() .

Questo gestore può eseguire un'elaborazione aggiuntiva in base alla chiave del blob.

L'applicazione può leggere parti di un valore Blobstore utilizzando un' interfaccia di streaming simile a un file. Consulta la classe BlobReader.

Caricamento di un blob

Per creare e caricare un blob:

1. Creare un URL di caricamento

Chiama blobstore.create_upload_url() per creare un URL di caricamento per il modulo che l'utente dovrà compilare, passando il percorso dell'applicazione da caricare al termine del POST del modulo.

upload_url = blobstore.create_upload_url("/upload_photo")

Esiste una versione asincrona, create_upload_url_async(). Consente al codice dell'applicazione di continuare a funzionare mentre Blobstore genera l'URL di caricamento.

2. Creare un modulo di caricamento

Il modulo deve includere un campo di caricamento file e 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 in Datastore, poi passa la richiesta riscritta alla tua applicazione nel percorso specificato come chiave blob.

3. Implementa il gestore dei caricamenti

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à informazioni del blob in Datastore. Tieni presente che dopo che l'utente ha inviato il modulo e il gestore è stato chiamato, il blob è già stato salvato e le relative informazioni sono state aggiunte a Datastore. Se la tua applicazione non vuole conservare il blob, devi eliminarlo immediatamente per evitare che diventi orfano.

Per tutte le app Flask, tutte le chiamate ai metodi della classe BlobstoreUploadHandler richiedono request.environ dictionary (richiesta importata dal modulo flask). Se la tua app è un'app WSGI senza un framework web, utilizza il parametro environ nel metodo get_uploads().

Quando Blobstore riscrive la richiesta dell'utente, i corpi delle parti MIME dei file caricati vengono svuotati 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 contenuti, l'archivio BLOB tenterà di dedurlo dall'estensione del file. Se non è possibile determinare un tipo di contenuti, al blob appena creato viene assegnato il tipo di contenuti application/octet-stream.

Pubblicazione di un blob

Per pubblicare i blob, devi includere un gestore del download dei blob come percorso nella tua applicazione. L'applicazione serve un blob impostando un'intestazione nella risposta in uscita. Se utilizzi Flask, la classe BlobstoreDownloadHandler richiede il dizionario request.environ (la richiesta viene importata dal modulo Flask). Se la tua app è un'app WSGI senza un framework web, utilizza il parametro environ nei metodi send_blob().. I blob possono essere pubblicati da qualsiasi URL dell'applicazione. Per pubblicare un blob nella tua applicazione, devi inserire un'intestazione speciale nella risposta contenente la chiave del blob. App Engine sostituisce il corpo della risposta con i contenuti del blob.

Intervalli di byte dei blob

Blobstore supporta la pubblicazione di parte di un valore elevato 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 dei byte è basata su zero. Un valore X-AppEngine-BlobRange vuoto incarica l'API di ignorare l'intestazione dell'intervallo e di 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 serve 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, il 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.

Applicazione di esempio completa

Consulta l'esempio di app Flask nella guida all'API Blobstore per Python 3.

Utilizzo del servizio Immagini con Blobstore

Il servizio Immagini può utilizzare un valore Blobstore come origine di una trasformazione. L'immagine di origine può avere le dimensioni massime per un valore Blobstore. Il servizio Immagini restituisce comunque l'immagine trasformata all'applicazione, quindi l'immagine trasformata deve essere inferiore a 32 megabyte. Questa opzione è utile per creare miniature di fotografie di grandi dimensioni caricate dagli utenti. Per informazioni sull'utilizzo del servizio Immagini con i valori di Blobstore, consulta la Documentazione del servizio di immagini.

Utilizzo dell'API Blobstore con 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 Cloud Storage e specificare il bucket e il nome file in blobstore.create_upload_url Parametro gs_bucket_name.

Nel gestore del caricamento, devi elaborare i metadati FileInfo e memorizzare esplicitamente il nome file di Cloud Storage necessario per recuperare il blob in un secondo momento.

Puoi anche pubblicare oggetti Cloud Storage utilizzando l'API Blobstore.

Se vuoi una soluzione di archiviazione di oggetti più moderna, valuta la possibilità di eseguire la migrazione da Blobstore di App Engine a Cloud Storage.

Utilizzo di BlobReader

Un'applicazione può leggere i dati dai valori di Blobstore utilizzando un'interfaccia simile a un oggetto file di Python. Questa interfaccia può iniziare a leggere un valore in qualsiasi posizione del byte e utilizza più chiamate di servizio e buffering, in modo che un'applicazione possa accedere alla dimensione completa del valore nonostante il limite di dimensione di una singola risposta alla chiamata di servizio.

La classe BlobReader può accettare uno dei tre valori come argomento del relativo costruttore:

L'oggetto implementa i metodi file di uso comune per la lettura del valore. L'applicazione non può modificare il valore di Blobstore; i metodi di scrittura dei file non sono implementati.

# Instantiate a BlobReader for a given Blobstore blob_key.
blob_reader = blobstore.BlobReader(blob_key)

# Instantiate a BlobReader for a given Blobstore blob_key, setting the
# buffer size to 1 MB.
blob_reader = blobstore.BlobReader(blob_key, buffer_size=1048576)

# Instantiate a BlobReader for a given Blobstore blob_key, setting the
# initial read position.
blob_reader = blobstore.BlobReader(blob_key, position=0)

# Read the entire value into memory. This may take a while depending
# on the size of the value and the size of the read buffer, and is not
# recommended for large values.
blob_reader_data = blob_reader.read()

# Write the contents to the response.
self.response.headers["Content-Type"] = "text/plain"
self.response.write(blob_reader_data)

# Set the read position back to 0, then read and write 3 bytes.
blob_reader.seek(0)
blob_reader_data = blob_reader.read(3)
self.response.write(blob_reader_data)
self.response.write("\n")

# Set the read position back to 0, then read and write one line (up to
# and including a '\n' character) at a time.
blob_reader.seek(0)
for line in blob_reader:
    self.response.write(line)

Invio di richieste asincrone

Un'applicazione può chiamare alcune funzioni di Blobstore che funzionano in background. Blobstore esegue la richiesta mentre l'applicazione esegue altre attività. Per effettuare la richiesta, l'applicazione chiama una funzione asincrona. La funzione restituisce immediatamente un oggetto RPC, che rappresenta la richiesta. Quando l'applicazione ha bisogno del risultato della richiesta, chiama il metodo get_result() dell'oggetto RPC.

Se il servizio non ha completato la richiesta quando l'applicazione chiama get_result(), il metodo attende fino al completamento della richiesta (o al raggiungimento della scadenza o al verificarsi di un errore). Il metodo restituisce l'oggetto risultato o genera un'eccezione se si è verificato un errore durante l'esecuzione della richiesta. Ad esempio, questo snippet di codice

upload_url = blobstore.create_upload_url('/upload')
slow_operation()
self.response.out.write("""<form action="%s" method="POST"
                           enctype="multipart/form-data">""" % upload_url)

diventa

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)

In questo esempio, l'applicazione esegue il codice slow_operation() contemporaneamente alla generazione dell'URL di caricamento da parte di Blobstore.

Quote e limiti

Lo spazio utilizzato per i valori di Blobstore contribuisce alla quota Dati archiviati (fatturabili). Le entità di informazioni sui blob in Datastore vengono conteggiate ai fini dei limiti relativi a Datastore. Tieni presente che Cloud Storage è un servizio a pagamento per utilizzo. Ti verrà addebitato il costo in base al listino prezzi di Cloud Storage.

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 all'utilizzo dell'archivio BLOB:

  • 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.