L'API Blobstore consente alla tua applicazione di pubblicare oggetti di dati, chiamati blob, di dimensioni molto maggiori rispetto a quelle 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 lo fanno 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 puoi utilizzare in un secondo momento per erogare il BLOB. L'applicazione può pubblicare il valore blob completo in risposta a una richiesta dell'utente oppure può leggere il valore direttamente utilizzando un'interfaccia simile a un file di streaming.
Introduzione a Blobstore
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 tramite una singola connessione HTTP. Questi oggetti sono chiamati valori Blobstore o blob.
I valori Blobstore vengono pubblicati come risposte dai gestori delle richieste e vengono creati come caricamenti tramite moduli web. Le applicazioni non creano direttamente i dati blob; i blob vengono invece creati indirettamente, tramite un modulo web inviato o un'altra richiesta HTTP POST.
I valori Blobstore possono essere pubblicati per l'utente o accessibili dall'applicazione in uno stream simile a un file, utilizzando l'API Blobstore.
Per chiedere a un utente di caricare un valore Blobstore, l'applicazione presenta un modulo web con un campo di caricamento file. L'applicazione genera l'URL dell'azione del modulo chiamando l'API Blobstore. Il browser dell'utente carica il file direttamente in Blobstore tramite l'URL generato. Blobstore archivia 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'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 blob.
I blob non possono essere modificati dopo la 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 contenuto. Puoi utilizzare la chiave blob per recuperare i record di informazioni blob ed eseguire query sulle relative proprietà.
Un'applicazione può leggere un valore Blobstore una porzione alla volta utilizzando una chiamata API.
La dimensione della porzione può essere fino alla dimensione massima di un valore restituito dall'API.
Questa dimensione è leggermente inferiore a 32 megabyte, rappresentata
in Java dalla costante com.google.appengine.api.blobstore.BlobstoreService.MAX_BLOB_FETCH_SIZE
.
Un'applicazione non può creare o modificare i valori Blobstore se non tramite i file caricati dall'utente.
Utilizzo di Blobstore
Le applicazioni possono utilizzare Blobstore per accettare file di grandi dimensioni come caricamenti dagli utenti e per pubblicare questi file. I file vengono chiamati blob una volta caricati. Le applicazioni
non accedono direttamente ai blobLe applicazioni interagiscono con i blob tramite le
entità di informazioni blob (rappresentate dalla classe
BlobInfo
) in
Datastore.
L'utente crea un blob inviando un modulo HTML che includa uno o più campi di immissione file. La tua applicazione
imposta
blobstoreService.createUploadUrl()
come la destinazione (l'azione) di questo modulo, passando alla funzione
un percorso dell'URL di un gestore nella tua 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
blobstoreService.createUploadUrl()
.
Questo gestore può eseguire un'ulteriore elaborazione in base alla chiave blob.
L'applicazione può leggere porzioni di un valore Blobstore utilizzando un
'interfaccia di streaming simile a un file. Consulta la classe BlobstoreInputStream.
Caricamento di un blob
Per creare e caricare un blob, segui questa procedura:
1. Crea un URL di caricamento
Chiama
blobstoreService.createUploadUrl()
per creare un URL di caricamento per il modulo che l'utente compilerà,
passando il percorso dell'applicazione da caricare al termine della richiesta POST del modulo.
<body>
<form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
<input type="file" name="myFile">
<input type="submit" value="Submit">
</form>
</body>
Tieni presente che questo è l'aspetto del modulo di caricamento se fosse stato creato come JSP.
2. Crea un modulo di caricamento
Il modulo deve includere un campo di caricamento file e il relativo enctype deve essere impostato su multipart/form-data. Quando l'utente invia il modulo, la richiesta POST viene gestita dall'API Blobstore, che crea il blob. L'API crea anche un record di informazioni per il blob, lo archivia in Datastore e passa la richiesta riscritta alla tua applicazione nel percorso specificato come chiave blob.
Non puoi utilizzare un bilanciatore del carico delle applicazioni esterno globale con un NEG serverless per gestire le richieste di caricamento inviate all'/_ah/upload/ URL
restituito dalla blobstore.create_upload_url chiamata.
Devi invece instradare queste richieste di caricamento direttamente al servizio App Engine. Puoi farlo utilizzando il dominio appspot.com o un dominio personalizzato mappato direttamente al servizio App Engine.
3. Implementa il gestore di caricamento
In questo gestore, puoi archiviare la chiave blob con il resto del modello dei dati dell'applicazione. La chiave blob stessa rimane accessibile dall'entità di informazioni blob in Datastore. Tieni presente che dopo che l'utente invia il modulo e viene chiamato il gestore, il blob è già stato salvato e le informazioni blob sono state aggiunte a Datastore. Se la tua applicazione non vuole conservare il blob, devi eliminarlo immediatamente per evitare che diventi orfano.
Nel codice seguente, getUploads restituisce un insieme di blob caricati. L'oggetto Map è un elenco che associa i nomi dei campi di caricamento ai blob che contengono.
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");
if (blobKeys == null || blobKeys.isEmpty()) {
res.sendRedirect("/");
} else {
res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
}
application/octet-stream al blob appena creato.
Pubblicazione di un blob
Per pubblicare i blob, devi includere un gestore di download dei blob come percorso nella tua applicazione.
Questo gestore deve passare la chiave blob per il blob desiderato a blobstoreService.serve(blobKey, res);
. In questo esempio, la chiave blob viene passata al gestore di download
come
l'argomento URL (req.getParameter('blob-key')).
In pratica, il gestore di download può ottenere la chiave blob con qualsiasi mezzo tu scelga, ad esempio tramite un altro metodo o un'azione dell'utente.
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
blobstoreService.serve(blobKey, res);
I blob possono essere pubblicati da qualsiasi URL dell'applicazione. Per erogare 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 una 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 di pubblicare il blob completo.
Ecco alcuni esempi di intervalli:
0-499pubblica i primi 500 byte del valore (byte da 0 a 499 inclusi).500-999pubblica 500 byte a partire dal 501° byte.500-pubblica tutti i byte a partire dal 501° byte fino alla fine del valore.-500pubblica gli ultimi 500 byte del valore.
Se l'intervallo di byte è valido per il valore Blobstore, Blobstore invia un codice di stato 206 Partial Content e l'intervallo di byte richiesto al client. 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.
Applicazione di esempio completa
Nell'applicazione di esempio seguente, l'URL principale dell'applicazione carica il modulo che chiede all'utente di caricare un file e il gestore di caricamento chiama immediatamente il gestore di download per pubblicare i dati. Questo per semplificare l'applicazione di esempio. In pratica, probabilmente non utilizzeresti l'URL principale per richiedere i dati di caricamento, né pubblicheresti immediatamente un blob appena caricato.
// file Upload.java
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
public class Upload extends HttpServlet {
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
@Override
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");
if (blobKeys == null || blobKeys.isEmpty()) {
res.sendRedirect("/");
} else {
res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
}
}
}
// file Serve.java
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
public class Serve extends HttpServlet {
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
blobstoreService.serve(blobKey, res);
}
}
// file index.jsp
<%@ page import="com.google.appengine.api.blobstore.BlobstoreServiceFactory" %>
<%@ page import="com.google.appengine.api.blobstore.BlobstoreService" %>
<%
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
%>
<html>
<head>
<title>Upload Test</title>
</head>
<body>
<form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
<input type="text" name="foo">
<input type="file" name="myFile">
<input type="submit" value="Submit">
</form>
</body>
</html>
// web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>Upload</servlet-class>
</servlet>
<servlet>
<servlet-name>Serve</servlet-name>
<servlet-class>Serve</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Serve</servlet-name>
<url-pattern>/serve</url-pattern>
</servlet-mapping>
</web-app>
Utilizzo del servizio Images con Blobstore
Il servizio Images può utilizzare un valore Blobstore come origine di una trasformazione. L'immagine di origine può avere una dimensione massima pari a quella di un valore Blobstore. Il servizio Images restituisce comunque l'immagine trasformata all'applicazione, quindi l'immagine trasformata deve essere inferiore a 32 megabyte. Questa funzionalità è utile per creare immagini miniatura di fotografie di grandi dimensioni caricate dagli utenti. Per informazioni sull'utilizzo del servizio Images con i valori Blobstore, consulta la documentazione del servizio Images.
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
BlobstoreService createUploadUrl,
specificare il nome del bucket nel parametro UploadOptions.
Nel gestore di caricamento, devi elaborare la mappa dei metadati FileInfo metadata e archiviare esplicitamente il nome file di Cloud Storage necessario per recuperare il blob in un secondo momento.
Puoi anche pubblicare gli oggetti Cloud Storage utilizzando l'API Blobstore.
I seguenti snippet di codice mostrano come farlo. Questo esempio si trova in un gestore delle richieste che ottiene il nome del bucket e il nome dell'oggetto nella richiesta. Crea il servizio Blobstore e lo utilizza per creare una chiave blob per Cloud Storage, utilizzando il bucket e il nome dell'oggetto forniti:BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
BlobKey blobKey = blobstoreService.createGsBlobKey(
"/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());
blobstoreService.serve(blobKey, resp);
Quote e limiti
Lo spazio utilizzato per i valori Blobstore contribuisce alla quota Dati archiviati (fatturabili). Le entità di informazioni blob in Datastore vengono conteggiate ai fini dei limiti relativi a Datastore. Tieni presente che Cloud Storage è un servizio a pagamento; ti verrà addebitato un costo in base al listino prezzi di Cloud Storage Cloud Storage.
Per ulteriori informazioni sulle quote di sicurezza a livello di sistema, consulta Quote.
Oltre alle quote di sicurezza a livello di sistema, i seguenti limiti si applicano in modo specifico all'utilizzo di Blobstore:
- La dimensione massima dei dati Blobstore che possono essere letti dall'applicazione con una chiamata API è di 32 megabyte.
- Il numero massimo di file che possono essere caricati in una singola richiesta POST del modulo è 500.