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 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 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 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 dell'archivio BLOB o BLOB. I valori dell'archivio BLOB vengono pubblicati come risposte dagli elaboratori 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 mostrati all'utente o essere accessibili dall'applicazione in uno 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 di azione del modulo chiamando l'API Blobstore. Il browser dell'utente carica il file direttamente nel Blobstore tramite l'URL generato. L'archivio BLOB archivia quindi il blob, riscrive la richiesta in modo che contenga la chiave BLOB e la passa a un percorso nell'applicazione. Un gestore delle richieste in quel percorso dell'applicazione può eseguire un'ulteriore elaborazione 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.

Dopo la creazione, i BLOB non possono essere modificati, 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à.

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 Java dalla costante com.google.appengine.api.blobstore.BlobstoreService.MAX_BLOB_FETCH_SIZE. Un'applicazione non può creare o modificare i valori dell'archivio BLOB se non tramite file caricati dall'utente.

Utilizzo di Blobstore

Le applicazioni possono utilizzare l'archivio BLOB 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. Le applicazioni utilizzano invece i BLOB tramite entità di informazioni BLOB (rappresentate dalla classe BlobInfo) nel datastore.

L'utente crea un blob inviando un modulo HTML che include uno o più campi di input del file. L'applicazione imposta blobstoreService.createUploadUrl() come destinazione (azione) di questo modulo, passando alla funzione il percorso dell'URL di un gestore nell'applicazione. Quando l'utente invia il modulo, il browser dell'utente carica i file specificati direttamente in Blobstore. L'archivio BLOB 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 ulteriori elaborazioni in base alla chiave BLOB.

L'applicazione può leggere parti di un valore Blobstore utilizzando un'interfaccia di streaming simile a un file. Visualizza il corso BlobstoreInputStream.

Caricamento di un blob

Per creare e caricare un blob, segui questa procedura:

1. Creare un URL di caricamento

Chiama blobstoreService.createUploadUrl 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.

<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 che avrebbe il modulo di caricamento se fosse creato come JSP.

2. Crea 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 informativo per il BLOB, archivia il record nel datastore e passa la richiesta riscritta all'applicazione sul percorso specificato come chiave BLOB.

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 blob stessa rimane accessibile dall'entità delle informazioni sul 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 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 contenevano.

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

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 di 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 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 nell'applicazione. Questo gestore deve passare la chiave del blob per il blob desiderato a blobstoreService.serve(blobKey, res);. In questo esempio, la chiave blob viene passata al gestore dei download come argomento URL (req.getParameter('blob-key')). In pratica, il gestore del download può recuperare la chiave del blob in qualsiasi modo 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 pubblicare un blob nell'applicazione, dovrai inserire un'intestazione speciale nella risposta contenente la chiave blob. App Engine sostituisce il corpo della risposta con il contenuto del blob.

Intervalli di byte dei blob

L'archivio BLOB supporta la gestione 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 (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 pubblica gli ultimi 500 byte del valore.

Se l'intervallo di byte è valido per il valore dell'archivio BLOB, quest'ultimo 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.

L'archivio BLOB 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.

// 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 dell'archivio BLOB 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 avere dimensioni inferiori a 32 megabyte. Questa funzionalità è utile per creare miniature di fotografie di grandi dimensioni caricate dagli utenti.

Per informazioni sull'utilizzo del servizio Images con i valori dell'archivio BLOB, consulta la documentazione del servizio immagini.

Utilizzo dell'API Blobstore con Google Cloud Storage

Puoi utilizzare l'API Blobstore per archiviare i BLOB in Cloud Storage anziché archiviarli in un archivio BLOB. Devi configurare un bucket come descritto nella documentazione di Google Cloud Storage e specificare il bucket e il nome file in BlobstoreService createUploadUrl, specifica il nome del bucket nel parametro UploadOptions. Nel gestore di caricamento, devi elaborare i metadati FileInfo restituiti e archiviare esplicitamente il nome file Google Cloud Storage necessario per recuperare il blob in un secondo momento.

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

I seguenti snippet di codice mostrano come eseguire questa operazione. Questo esempio si trova in un gestore di richieste che recupera il nome del bucket e dell'oggetto nella richiesta. Crea il servizio Blobstore e lo utilizza per creare una chiave BLOB per Google Cloud Storage, utilizzando il nome del bucket e 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 di Blobstore contribuisce alla quota Dati archiviati (fatturabili). Le entità delle informazioni BLOB nel datastore vengono conteggiate ai fini del datastore limiti. Tieni presente che Google Cloud Storage è un servizio a pagamento per utilizzo; ti verrà addebitato in base al listino prezzi di Cloud Storage.

Per ulteriori informazioni sulle quote di sicurezza a livello di sistema, consulta la sezione 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.