Importer des images avec l'API Play Games Services Publishing

L'API Play Games Services Publishing vous permet d'importer une image pour une ressource de jeu.

Options d'importation

L'API Play Games Services Publishing vous permet d'importer certains types de données binaires, ou "médias". Les caractéristiques spécifiques des données que vous pouvez importer sont spécifiées sur la page de référence pour toutes les méthodes compatibles avec l'importation de médias :

  • Taille maximale du fichier d'importation : quantité maximale de données que vous pouvez stocker à l'aide de cette méthode.

  • Types MIME de médias acceptés : types de données binaires que vous pouvez stocker à l'aide de cette méthode.

Vous pouvez effectuer des requêtes d'importation via l'une des méthodes indiquées ci-dessous. Spécifiez la méthode que vous utilisez avec le paramètre de requête uploadType.

  • Importation simple : uploadType=media. Permet de transférer rapidement des fichiers de petite taille, par exemple de 5 Mo ou moins.

  • Importation en plusieurs parties : uploadType=multipart. Permet le transfert rapide des fichiers de petite taille et de leurs métadonnées. Le fichier est transféré avec les métadonnées qui le décrivent dans une seule requête.

  • Importation avec reprise : uploadType=resumable. Permet un transfert fiable, ce qui est particulièrement important avec des fichiers plus volumineux. Avec cette méthode, vous utilisez une requête de lancement de session qui peut éventuellement inclure des métadonnées. Il s'agit d'une bonne stratégie à utiliser pour la plupart des applications, car elle fonctionne également pour des fichiers plus petits au prix d'une requête HTTP supplémentaire par importation.

Lorsque vous importez du contenu multimédia, vous utilisez un URI spécial. En fait, les méthodes compatibles avec l'importation de contenus multimédias possèdent deux points de terminaison URI:

  • URI /upload pour les médias. Le format du point de terminaison de l'importation correspond à l'URI de ressource standard avec le préfixe "/upload". Utilisez cet URI lors du transfert des données du média.

    Exemple : POST /upload/games/v1configuration/images/resourceId/imageType/imageType

  • URI de ressource standard pour les métadonnées. Si la ressource contient des champs de données, ces champs sont utilisés pour stocker les métadonnées décrivant le fichier importé. Vous pouvez utiliser cet URI pour créer ou mettre à jour des valeurs de métadonnées.

    Exemple : POST /games/v1configuration/images/resourceId/imageType/imageType

Importation simple

La méthode la plus simple pour importer un fichier consiste à effectuer une requête d'importation simple. Cette option est recommandée dans les cas suivants :

  • Le fichier est suffisamment petit pour être réimporté dans son intégralité en cas d'échec de connexion.

  • Aucune métadonnée ne doit être envoyée. Par exemple, vous prévoyez d'envoyer des métadonnées pour cette ressource dans une requête distincte, ou les métadonnées ne sont pas disponibles ou prises en charge. Pour utiliser l'importation simple, envoyez une requête POST ou PUT à l'URI /upload de la méthode et ajoutez le paramètre de requête uploadType=media. Par exemple :

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media

Voici les en-têtes HTTP à utiliser lors d'une requête d'importation simple :

  • Content-Type : spécifiez-y l'un des types de données de médias d'importation acceptés par la méthode, comme indiqué dans la documentation de référence de l'API Publishing.

  • Content-Length : spécifiez-y le nombre d'octets que vous importez. Cet en-tête n'est pas obligatoire si vous utilisez l'encodage de transfert fragmenté.

Exemple : importation simple

L'exemple suivant illustre l'utilisation d'une requête d'importation simple pour l'API Play Games Services Publishing.

POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=media HTTP/1.1
Host: www.googleapis.com
Content-Type: image/png
Content-Length: number_of_bytes_in_file
Authorization: Bearer your_auth_token

PNG data

Si la requête aboutit, le serveur affiche le code d'état HTTP 200 OK avec toutes les métadonnées. Par exemple :

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Importation en plusieurs parties

Si vous souhaitez envoyer des métadonnées avec les données à importer, vous pouvez effectuer une seule requête multipart/related. Cette opération est judicieuse si les données que vous envoyez sont suffisamment petites pour pouvoir être importées intégralement en cas d'échec de connexion.

Pour utiliser l'importation en plusieurs parties, envoyez une requête POST ou PUT à l'URI /upload de la méthode, puis ajoutez le paramètre de requête uploadType=multipart. Par exemple :

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart

Voici les en-têtes HTTP de premier niveau à utiliser lors d'une importation en plusieurs parties :

Content-Type : spécifiez-y "multipart/related" et ajoutez la chaîne de délimitation que vous utilisez pour identifier les parties de la requête.

Content-Length : spécifiez-y le nombre total d'octets dans le corps de la requête. La partie média de la requête doit être inférieure à la taille de fichier maximale définie pour cette méthode.

Le corps de la requête est mis en forme en tant que type de contenu "multipart/related" RFC2387 et contient exactement deux parties. Les parties sont identifiées par une chaîne de délimitation, et la dernière chaîne est suivie de deux traits d'union.

Chaque partie de la requête en plusieurs parties nécessite un en-tête Content-Type supplémentaire :

  • Partie métadonnées : doit apparaître en premier. La valeur Content-Type doit correspondre à l'un des formats de métadonnées acceptés.

  • Partie média : doit apparaître en second. La valeur Content-Type doit correspondre à l'un des types MIME de médias acceptés pour la méthode.

Consultez la documentation de référence de l'API Publishing afin d'obtenir la liste des types MIME de médias acceptés et des limites de taille pour les fichiers importés, pour chaque méthode.

Exemple : Importation en plusieurs parties

L'exemple ci-dessous présente une requête d'importation en plusieurs parties pour l'API Play Games Services Publishing.

POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=multipart HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=foo_bar_baz
Content-Length: number_of_bytes_in_entire_request_body

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

--foo_bar_baz
Content-Type: image/png

PNG data
--foo_bar_baz--

Si la requête aboutit, le serveur affiche le code d'état HTTP 200 OK avec toutes les métadonnées :

HTTP/1.1 200
Content-Type: application/json

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

Importation avec reprise

Pour importer des fichiers de données de manière plus fiable, vous pouvez utiliser le protocole d'importation avec reprise. Celui-ci vous permet de reprendre une opération d'importation après un échec de communication ayant interrompu le flux de données. Cette opération est particulièrement utile si vous transférez des fichiers volumineux et que les risques d'interruption du réseau ou d'échec de transmission sont élevés, par exemple si l'importation est réalisée depuis une application cliente mobile. Cela peut également réduire l'utilisation de la bande passante en cas de panne réseau, car cela vous évite de redémarrer les importations de fichiers volumineux depuis le début.

Pour réaliser une importation avec reprise, procédez comme suit :

  1. Démarrez une session avec reprise. Effectuez une requête initiale contenant les métadonnées à l'URI d'importation, le cas échéant.

  2. Enregistrez l'URI de la session avec reprise. Enregistrez l'URI de la session affichée dans la réponse à la requête initiale. Vous l'utiliserez pour les requêtes restantes dans cette session. Importez le fichier.

  3. Envoyez le fichier de médias à l'URI de la session avec reprise.

En outre, les applications qui utilisent l'importation avec reprise doivent inclure le code nécessaire pour reprendre une importation interrompue. En cas d'interruption de l'importation, déterminez la quantité de données reçue, puis reprenez l'importation à partir de ce point.

Démarrer une session avec reprise

Pour lancer une importation avec reprise, envoyez une requête POST ou PUT à l'URI /upload de la méthode, puis ajoutez le paramètre de requête uploadType=resumable. Par exemple :

POST https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable

Le corps de cette requête de lancement doit être vide ou ne contenir que les métadonnées. Vous transférerez le contenu réel du fichier que vous souhaitez importer dans les requêtes ultérieures.

Utilisez les en-têtes HTTP suivants avec la requête initiale :

  • X-Upload-Content-Type : définissez le type MIME du média pour les données d'importation à transférer dans les requêtes ultérieures.

  • X-Upload-Content-Length : définissez le nombre d'octets des données d'importation à transférer dans les requêtes ultérieures. Si cette valeur est inconnue au moment de la requête, vous pouvez omettre cet en-tête.

  • Si vous fournissez des métadonnées : Content-Type. Définissez cette valeur en fonction du type de données des métadonnées.

  • Content-Length : définissez le nombre d'octets fournis dans le corps de cette requête initiale. Cet en-tête n'est pas obligatoire si vous utilisez l'encodage de transfert fragmenté.

Consultez la documentation de référence de l'API Publishing afin d'obtenir la liste des types MIME de médias acceptés et des limites de taille pour les fichiers importés, pour chaque méthode.

Exemple : Requête de lancement de session avec reprise

L'exemple suivant montre comment lancer une session avec reprise pour l'API Play Games Services Publishing.

POST /upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: image/png
X-Upload-Content-Length: 2000000

{
  "kind": "gamesConfiguration#imageConfiguration",
  "url": string,
  "resourceId": string,
  "imageType": string
}

La section suivante décrit comment gérer la réponse.

Enregistrer l'URI de la session avec reprise

Si la requête de lancement de session aboutit, le serveur d'API répond par un code d'état HTTP 200 OK. En outre, il fournit un en-tête Location qui spécifie votre URI de session avec reprise. L'en-tête Location, illustré dans l'exemple ci-dessous, inclut une partie de paramètre de requête upload_id qui fournit l'ID d'importation unique à utiliser pour cette session.

Exemple : Réponse de lancement de session avec reprise

La réponse à la requête de l'étape 1 se présente comme suit :

HTTP/1.1 200 OK
Location: https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2
Content-Length: 0

La valeur de l'en-tête Location, comme indiqué dans l'exemple de réponse ci-dessus, correspond à l'URI de session que vous utiliserez comme point de terminaison HTTP afin d'effectuer l'importation du fichier ou d'interroger le statut de l'importation.

Copiez et enregistrez l'URI de la session afin de pouvoir l'utiliser pour les requêtes ultérieures.

Importer le fichier

Pour importer le fichier, envoyez une requête PUT à l'URI d'importation obtenu lors de l'étape précédente. Le format de la requête d'importation se présente comme suit :

PUT session_uri

Les en-têtes HTTP à utiliser lors des requêtes d'importation de fichiers avec reprise incluent Content-Length. Définissez cette valeur sur le nombre d'octets que vous importez dans cette requête, qui correspond généralement à la taille du fichier à importer.

Exemple : Requête d'importation de fichier avec reprise

Voici une requête avec reprise permettant d'importer l'intégralité du fichier PNG de 2 000 000 octets pour l'exemple actuel.

PUT https://www.googleapis.com/upload/games/v1configuration/images/resourceId/imageType/imageType?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1
Content-Length: 2000000
Content-Type: image/png

bytes 0-1999999

Si la requête aboutit, le serveur envoie une réponse HTTP 201 Created, ainsi que toutes les métadonnées associées à cette ressource. Si la requête initiale de la session avec reprise était PUT, la réponse qui aboutit indiquerait 200 OK pour mettre à jour une ressource existante, avec toutes les métadonnées associées à cette ressource.

Si la requête d'importation est interrompue ou si le serveur vous envoie une réponse HTTP 503 Service Unavailable ou toute autre réponse 5xx, suivez la procédure expliquant comment reprendre une importation interrompue.


Importer le fichier en fragments

Les importations avec reprise vous permettent de diviser un fichier en plusieurs fragments et d'envoyer une série de requêtes afin d'importer chacun de ces fragments l'un après l'autre. Cette méthode n'est pas conseillée, car des coûts de performance sont associés aux requêtes supplémentaires, ce qui n'est généralement pas nécessaire. Toutefois, vous pouvez avoir recours à la fragmentation pour réduire la quantité de données transférées dans une seule requête. Cette approche est utile lorsque le temps imparti à chaque requête est limité, comme c'est le cas pour certaines classes de requêtes Google App Engine. Elle vous permet également de fournir des indications concernant la progression de l'importation pour les anciens navigateurs qui ne possèdent pas cette fonctionnalité par défaut.

Si vous importez les données en fragments, l'en-tête Content-Range est également obligatoire, ainsi que l'en-tête Content-Length pour les importations de fichiers complets :

  • Content-Length : définissez la taille des fragments ou une valeur inférieure, comme cela pourrait être le cas pour la dernière requête.

  • Content-Range : indiquez les octets du fichier que vous importez. Par exemple, Content-Range: bytes 0-524287/2000000 indique que vous fournissez les 524 288 premiers octets (256 x 1 024 x 2) dans un fichier de 2 000 000 octets.

Exemple : Requête d'importation de fichier fragmenté avec reprise

Voici à quoi pourrait ressembler une requête qui envoie les 524 288 premiers octets :

PUT {session_uri} HTTP/1.1
Host: www.googleapis.com
Content-Length: 524288
Content-Type: image/png
Content-Range: bytes 0-524287/2000000

bytes 0-524288

Si la requête aboutit, le serveur renvoie une réponse 308 Resume Incomplete, ainsi qu'un en-tête Range qui identifie le nombre total d'octets stockés jusqu'à présent :

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: bytes=0-524287

Utilisez la valeur supérieure affichée dans l'en-tête Range pour déterminer où démarrer le prochain fragment. Continuez à utiliser PUT pour chaque fragment du fichier jusqu'à l'importation du fichier entier.

Si la requête PUT d'un fragment est interrompue ou si le serveur vous envoie une réponse HTTP 503 Service Unavailable ou toute autre réponse 5xx, suivez la procédure expliquant comment reprendre une importation interrompue. Toutefois, plutôt que d'importer le reste du fichier, continuez à importer des fragments à partir de ce point.

Remarques importantes :

  • Veillez à utiliser l'en-tête Range dans la réponse pour déterminer où démarrer le prochain fragment. Ne partez pas du principe que le serveur a reçu tous les octets envoyés dans la requête précédente.

  • Chaque URI d'importation possède une durée de vie limitée et finit par expirer (dans un délai d'environ un jour, s'il n'est pas utilisé). Pour cette raison, il est préférable de démarrer une importation avec reprise dès que vous obtenez l'URI d'importation et de reprendre l'importation peu après son interruption.

  • Si vous envoyez une requête avec un ID de session d'importation arrivé à expiration, le serveur renvoie un code d'état 404 Not Found. Lorsqu'une erreur non récupérable se produit dans la session d'importation, le serveur renvoie un code d'état 410 Gone. Dans ce cas, vous devez lancer une nouvelle importation avec reprise, obtenir un nouvel URI d'importation et reprendre l'importation depuis le début à l'aide du nouveau point de terminaison.

Une fois l'importation du fichier terminée, le serveur renvoie une réponse HTTP 201 Created ainsi que toutes les métadonnées associées à cette ressource. Si cette requête avait mis à jour une entité existante au lieu d'en créer une, le code de réponse HTTP pour une importation terminée aurait été 200 OK.


Reprendre une importation interrompue

Si une requête d'importation est interrompue avant de recevoir une réponse ou si le serveur vous envoie une réponse HTTP 503 Service Unavailable, vous devez reprendre l'importation interrompue. Pour reprendre une importation interrompue, procédez comme suit :

  1. État de la demande. Interrogez l'état actuel de l'importation en envoyant une requête PUT vide à l'URI d'importation. Pour cette requête, les en-têtes HTTP doivent inclure un en-tête Content-Range indiquant que la position actuelle dans le fichier est inconnue. Par exemple, définissez Content-Range sur */2000000 si la longueur totale de votre fichier correspond à 2 000 000. Si vous ignorez la taille totale du fichier, définissez la valeur Content-Range sur */*.

  2. Obtenir le nombre d'octets importés Traitez la réponse à partir de la requête d'état. Le serveur utilise l'en-tête Range dans sa réponse pour spécifier les octets reçus jusqu'à présent. Par exemple, un en-tête Range de 0-299999 indique que les 300 000 premiers octets du fichier ont été reçus.

  3. Importer les données restantes Enfin, maintenant que vous savez où reprendre la requête, envoyez les données restantes ou le fragment actuel. Notez que vous devez traiter les données restantes comme un fragment séparé dans tous les cas. Vous devez donc envoyer l'en-tête Content-Range au moment de la reprise de l'importation.

Exemple : Reprendre une importation interrompue

  1. Interrogez l'état de l'importation. La requête suivante utilise l'en-tête Content-Range pour indiquer que la position actuelle dans le fichier de 2 000 000 octets est inconnue.

    PUT {session_uri} HTTP/1.1
    Content-Length: 0
    Content-Range: bytes */2000000
    
  2. Procédez à l'extraction du nombre d'octets importés jusqu'à présent à partir de la réponse. La réponse du serveur utilise l'en-tête Range pour indiquer qu'il a reçu les 43 premiers octets du fichier jusqu'à présent. Utilisez la valeur supérieure de l'en-tête Range pour déterminer où démarrer la reprise de l'importation.

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42
  1. Reprenez l'importation là où elle s'était arrêtée. La requête suivante reprend l'importation en envoyant les octets restants du fichier, en commençant par l'octet 43.
PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

Bonnes pratiques

En ce qui concerne l'importation de médias, il est utile de connaître certaines bonnes pratiques concernant le traitement des erreurs.

  • Reprenez ou relancez les importations qui échouent en raison d'interruptions de connexion ou d'erreurs 5xx, parmi lesquelles :

    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Si une erreur de serveur 5xx est renvoyée lors de la reprise ou de la nouvelle tentative d'importation, utilisez une stratégie d'intervalle exponentiel entre les tentatives. Ces erreurs peuvent se produire quand un serveur est surchargé. L'intervalle exponentiel entre les tentatives peut contribuer à résoudre ce type de problème lors des pics de volumes de requêtes ou de trafic réseau.

  • Les autres types de requêtes ne doivent pas être traités par un intervalle exponentiel entre les tentatives, mais vous pouvez toujours essayer d'en relancer un certain nombre. Lorsque vous relancez ces requêtes, limitez le nombre de tentatives. Par exemple, votre code peut établir une limite de 10 tentatives ou moins avant de signaler une erreur.

  • Lorsque vous effectuez des importations avec reprise, traitez les erreurs 404 Not Found et 410 Gone en recommençant toute l'importation depuis le début.

Intervalle exponentiel entre les tentatives

L'intervalle exponentiel entre les tentatives est une stratégie standard de traitement d'erreurs pour les applications réseau, selon laquelle le client relance périodiquement une requête ayant échoué sur une durée de plus en plus longue. Si un volume élevé de requêtes ou un trafic réseau important provoquent des erreurs sur le serveur, l'intervalle exponentiel entre les tentatives peut s'imposer comme une stratégie efficace pour traiter ces erreurs. À l'inverse, cette stratégie n'est pas pertinente pour traiter les erreurs sans rapport avec le volume réseau ou les temps de réponse, telles que les erreurs associées aux identifiants d'autorisation non valides ou aux fichiers introuvables.

Utilisé correctement, l'intervalle exponentiel entre les tentatives augmente l'efficacité de l'utilisation de la bande passante, réduit le nombre de requêtes nécessaires pour obtenir une réponse positive et optimise le débit des requêtes dans les environnements avec simultanéité.

Le fonctionnement de l'intervalle exponentiel simple entre les tentatives se présente comme suit :

  1. Vous envoyez une requête à l'API.
  2. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  3. Vous patientez 1 seconde + "random_number_milliseconds", puis vous relancez la requête.
  4. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  5. Vous patientez 2 secondes + "random_number_milliseconds", puis vous relancez la requête.
  6. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  7. Vous patientez 4 secondes + "random_number_milliseconds", puis vous relancez la requête.
  8. Vous recevez HTTP 503 response, qui indique que vous devez relancer la requête.
  9. Vous patientez 8 secondes + "random_number_milliseconds", puis vous relancez la requête.
  10. Vous recevez HTTP 503 response, qui indique que vous devez relancer la requête.
  11. Vous patientez 16 secondes + "random_number_milliseconds", puis vous relancez la requête.
  12. Vous arrêtez, puis vous signalez ou consignez une erreur.

Dans la liste ci-dessus, "random_number_milliseconds" est un nombre aléatoire de millisecondes inférieur ou égal à 1 000. Cette valeur est nécessaire, car l'introduction d'un faible délai aléatoire contribue à répartir la charge de manière plus uniforme et à éviter la surcharge du serveur. La valeur de "random_number_milliseconds" doit être redéfinie après chaque temps d'attente.

L'algorithme est configuré pour se terminer lorsque "n" vaut 5. Ce plafond empêche les clients d'effectuer des relances indéfiniment et entraîne un délai total d'environ 32 secondes avant qu'une requête ne soit considérée comme une "erreur non récupérable". Vous pouvez tout à fait définir un nombre maximal de tentatives plus élevé, surtout si une longue importation est en cours d'exécution. Veillez simplement à limiter le délai des nouvelles tentatives de manière raisonnable, par exemple à moins d'une minute.

Guides des bibliothèques clientes des API