Présentation de l'API Blobstore pour Java 8

Remarque : Nous vous recommandons d'utiliser Google Cloud Storage plutôt que Blobstore pour stocker les données de blobs.

L'API Blobstore permet à votre application de diffuser des objets de données, appelés objets blob, beaucoup plus volumineux que la taille autorisée pour les objets dans le service Datastore. Les objets blob sont particulièrement utiles pour la diffusion de fichiers de grande taille, tels que des fichiers vidéo ou image, ainsi que pour le transfert de fichiers de données volumineux. Les objets blob sont créés lorsqu'un fichier est téléchargé via une requête HTTP. Pour ce faire, vos applications présentent généralement à l'utilisateur un formulaire avec un champ de téléchargement de fichier. Une fois ce formulaire envoyé, le Blobstore crée un objet blob à partir du contenu du fichier et renvoie une référence opaque à l'objet blob, appelée clé blob, que vous pouvez ensuite utiliser pour diffuser l'objet blob. L'application peut diffuser la valeur complète du blob en réponse à une demande d'utilisateur. Elle peut aussi lire directement la valeur à l'aide d'une interface de type fichier en streaming.

Présentation du Blobstore

Google App Engine inclut le service Blobstore, qui permet aux applications de diffuser des objets de données limités uniquement par la quantité de données pouvant être importées ou téléchargées via une seule connexion HTTP. Ces objets sont appelés valeurs Blobstore ou objets blob. Les valeurs Blobstore sont diffusées en tant que réponses par des gestionnaires de requêtes et créées en tant que transferts via des formulaires Web. Les applications ne créent pas directement de données blob. En effet, les objets blob sont créés indirectement, par un formulaire Web envoyé ou une autre demande HTTP POST. Les valeurs de Blobstore peuvent être diffusées vers l'utilisateur ou accessibles par l'application dans un flux de type fichier, à l'aide de l'API Blobstore.

Pour inviter un utilisateur à importer une valeur Blobstore, votre application présente un formulaire Web avec un champ d'importation de fichier. L'application génère l'URL d'action du formulaire en appelant l'API Blobstore. Le navigateur de l'utilisateur importe le fichier directement dans le Blobstore via l'URL générée. Blobstore stocke ensuite l'objet blob, réécrit la demande de manière qu'elle inclue la clé de l'objet blob et la transmet à un chemin dans votre application. Un gestionnaire de demandes situé sur ce chemin dans votre application peut alors procéder au traitement approfondi du formulaire.

Pour diffuser un objet blob, votre application définit un en-tête sur la réponse sortante et App Engine remplace la réponse par la valeur de l'objet blob.

Une fois créés, les objets blob ne peuvent pas être modifiés. Cependant, ils peuvent être supprimés. Chaque objet blob est associé à un enregistrement d'informations, stocké dans le datastore. Cet enregistrement fournit des détails, tels que la date de création et le type de contenu de cet objet blob. Vous pouvez utiliser la clé blob pour récupérer des enregistrements d'informations relatifs aux objets blob et interroger leurs propriétés.

Une application peut lire une valeur de Blobstore portion par portion, à l'aide d'un appel d'API. La taille de chaque portion est limitée par la taille maximale d'une valeur renvoyée par l'API. Cela correspond à un peu moins de 32 Mo et à la constante com.google.appengine.api.blobstore.BlobstoreService.MAX_BLOB_FETCH_SIZE dans Java. Une application ne peut créer ou modifier des valeurs Blobstore que par le biais des fichiers importés par l'utilisateur.

Utilisation du Blobstore

Les applications peuvent utiliser le Blobstore pour accepter l'importation des fichiers volumineux par les utilisateurs et pour diffuser ces fichiers. Une fois importés, les fichiers sont appelés des objets blob. Les applications n'accèdent pas directement aux objets blob. Au lieu de cela, les applications fonctionnent avec des blobs via des entités d'informations de blobs (représentées par la classe BlobInfo) dans le datastore.

L'utilisateur crée un objet blob en soumettant un formulaire HTML qui inclut un ou plusieurs champs de saisie de fichiers. Votre application définit blobstoreService.createUploadUrl() comme destination (action) de ce formulaire, en transmettant à la fonction le chemin d’URL d’un gestionnaire dans votre application. Lorsque l'utilisateur envoie le formulaire, le navigateur de l'utilisateur transfère directement les fichiers indiqués au Blobstore. Le Blobstore réécrit la demande de l'utilisateur et stocke les données du fichier importé, en remplaçant les données du fichier importé par une ou plusieurs clés d'objets blob correspondantes, puis transmet la demande réécrite au gestionnaire au chemin d'URL que vous avez fourni à blobstoreService.createUploadUrl(). Ce gestionnaire peut procéder à un traitement supplémentaire en fonction de la clé blob.

L'application peut lire des portions d'une valeur Blobstore à l'aide d'une interface de diffusion en continu de type fichier. Consultez la classe BlobstoreInputStream.

Importer un objet blob

Pour créer et transférer un objet blob, suivez cette procédure :

1. Créez une URL d'importation

Appelez blobstoreService.createUploadUrl pour créer une URL d'importation pour le formulaire à remplir par l'utilisateur, en transférant le chemin de l'application à charger lorsque le POST du formulaire est terminé.

<body>
    <form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
        <input type="file" name="myFile">
        <input type="submit" value="Submit">
    </form>
</body>

Cela permet de voir comment le formulaire de transfert apparaîtrait s'il était créé en tant que JSP.

2. Créez un formulaire d'importation

Le formulaire doit inclure un champ d'importation de fichier et la valeur enctype du formulaire doit être définie sur multipart/form-data. Lorsque l'utilisateur envoie le formulaire, la requête POST est traitée par l'API Blobstore, ce qui entraîne la création de l'objet blob. L’API crée également un enregistrement d’informations pour l'objet blob et le stocke dans le datastore, puis transmet la demande réécrite à votre application sur le chemin donné en tant que clé d'objet blob.

3. Implémentez le gestionnaire d'importation

Dans ce gestionnaire, vous pouvez stocker la clé blob avec le reste du modèle de données de l'application. La clé blob elle-même reste accessible à partir de l'entité d'informations relatives à l'objet blob dans le magasin de données. Notez qu'une fois que l'utilisateur a soumis le formulaire et que votre gestionnaire a été appelé, l'objet blob a déjà été sauvegardé et les informations associées ajoutées au magasin de données. Si votre application ne souhaite pas conserver l'objet blob, vous devez le supprimer immédiatement pour éviter qu'il ne devienne orphelin :

Dans le code suivant, getUploads renvoie un ensemble d'objets blob qui ont été importés. L'objet Map est une liste qui associe les noms des champs d'importation aux objets blob qu'ils contiennent.

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

Lorsque le Blobstore réécrit la requête de l'utilisateur, le corps des parties MIME des fichiers importés est vidé et la clé blob est ajoutée en tant qu'en-tête de la partie MIME. Tous les autres champs et parties du formulaire sont préservés et transmis au gestionnaire de transferts. Si vous ne spécifiez pas de type de contenu, le Blobstore tentera de l'inférer à partir de l'extension du fichier. S'il n'est pas possible de déterminer un type de contenu, l'objet blob nouvellement créé se voit attribuer le type de contenu application/octet-stream.

Diffuser un blob

Pour diffuser des objets blob, vous devez inclure un gestionnaire de téléchargement d'objet blob en tant que chemin d'accès dans votre application. Ce gestionnaire doit transmettre la clé de l'objet blob souhaité à blobstoreService.serve(blobKey, res);. Dans cet exemple, la clé d'objet blob est transmise au gestionnaire de téléchargement en tant qu'argument d'URL (req.getParameter('blob-key')). Dans la pratique, le gestionnaire de téléchargement peut obtenir la clé blob par n'importe quel moyen de votre choix, par exemple via une autre méthode ou action utilisateur.

public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws IOException {
        BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
        blobstoreService.serve(blobKey, res);

Les objets blob peuvent être transmis à partir de n'importe quelle URL d'application. Pour diffuser un objet blob dans votre application, vous devez mettre un en-tête spécial dans la réponse contenant la clé de l'objet blob. App Engine remplace le corps de la réponse par le contenu de l'objet blob.

Plages d'octets des objets blob

Le Blobstore prend en charge la diffusion d’une partie d’une valeur importante au lieu de la valeur complète en réponse à une demande. Pour diffuser une valeur partielle, incluez l'en-tête X-AppEngine-BlobRange dans la réponse sortante. Sa valeur correspond à une plage d'octets HTTP standard. La numérotation des octets est basée sur zéro. Une valeur X-AppEngine-BlobRange vide indique à l'API d'ignorer l'en-tête de la plage et de diffuser l'objet blob complet. Exemples de plages :

  • 0-499 : diffuse les 500 premiers octets de la valeur (octets 0 à 499 inclus).
  • 500-999 : diffuse 500 octets à partir du 501e octet.
  • 500- : diffuse tous les octets à partir du 501e octet, jusqu'à la fin de la valeur.
  • -500 : diffuse les 500 derniers octets de la valeur.

Si la plage d'octets est valide pour la valeur Blobstore, celui-ci envoie un code de statut 206 Content Partial et la plage d'octets demandée au client. Si la plage n'est pas valide pour la valeur, le Blobstore envoie 416 Requested Range Not Satisfiable.

Le Blobstore ne prend pas en charge plusieurs plages d'octets dans une même demande (par exemple, 100-199,200-299), qu'elles se chevauchent ou non.

Exemple d'application complète

Dans l'exemple d'application suivant, l'URL principale de l'application charge le formulaire qui demande un fichier à importer à l'utilisateur, et le gestionnaire d'importation appelle immédiatement le gestionnaire de téléchargement pour diffuser les données. Cela permet de simplifier l'exemple d'application. En pratique, il est peu probable que vous utilisiez l'URL principale pour demander un transfert de données, ou encore que vous diffusiez un objet blob immédiatement après l'avoir transféré.

// 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>

Utiliser le service Images avec le Blobstore

Le service Images peut utiliser une valeur Blobstore comme source d'une transformation. La taille de l'image source est limitée par la taille maximale d'une valeur Blobstore. Le service Images renvoie encore l'image transformée à l'application. Par conséquent, l'image transformée doit être inférieure à 32 mégaoctets. Cela est utile pour créer des vignettes des photos volumineuses transférées par les utilisateurs.

Pour plus d'informations sur l'utilisation du service Images avec les valeurs Blobstore, consultez la documentation du service Images.

Utiliser l'API Blobstore avec Google Cloud Storage

Vous pouvez utiliser l'API Blobstore pour stocker des objets blob dans Cloud Storage au lieu de les stocker dans Blobstore. Vous devez configurer un bucket comme décrit dans la documentation de Google Cloud Storage et spécifier le bucket et le nom de fichier dans BlobstoreService createUploadUrl, puis spécifier le nom du bucket dans le paramètre UploadOptions. Dans le gestionnaire d'importation, vous devez traiter les métadonnées FileInfo renvoyées et stocker explicitement le nom de fichier Google Cloud Storage nécessaire pour récupérer l'objet blob ultérieurement.

Vous pouvez également diffuser des objets Cloud Storage à l'aide de l'API Blobstore.

Les extraits de code suivants montrent comment procéder. Cet exemple provient d'un gestionnaire de requêtes qui obtient le nom du bucket et le nom de l'objet dans la requête. Il crée le service Blobstore et l'utilise pour créer une clé d'objet blob pour Google Cloud Storage, à l'aide du bucket et du nom d'objet fournis :

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
BlobKey blobKey = blobstoreService.createGsBlobKey(
    "/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());
blobstoreService.serve(blobKey, resp);

Quotas et limites

L'espace utilisé pour les valeurs Blobstore est décompté dans le quota Stored Data (billable) (Données stockées (facturables)). Les entités d'informations d'objets blob du datastore sont comptabilisées dans les limites associées au datastore. Notez que Google Cloud Storage est un service payant. Vous serez facturé selon la grille tarifaire de Cloud Storage.

Pour en savoir plus sur les quotas de sécurité à l'échelle du système, consultez la rubrique Quotas.

Outre les quotas de sécurité à l'échelle du système, les limites suivantes s'appliquent spécifiquement à l'utilisation du Blobstore :

  • La taille maximale des données Blobstore lisibles par l'application avec un seul appel d'API est de 32 mégaoctets.
  • Le nombre maximal de fichiers importables dans un seul formulaire POST est de 500.
Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Environnement standard App Engine pour Java 8