L'API Gmail vous permet d'importer des données de fichiers lors de la création ou de la mise à jour d'un brouillon, ou lors de l'insertion ou de l'envoi d'un message.
Options d'importation
L'API Gmail vous permet d'importer certains types de données binaires (ou fichiers multimé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 exposé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 plus petits, par exemple de 5 Mo ou moins. - Importation en plusieurs parties :
uploadType=multipart
. Pour un transfert rapide de petits fichiers et métadonnées ; transfère le fichier avec les métadonnées qui le décrivent dans une seule requête. - Importation avec reprise :
uploadType=resumable
. Pour un transfert fiable, 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 un média, vous utilisez un URI spécial. Concrètement, les méthodes compatibles avec l'importation de mé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 un préfixe "/upload". Utilisez cet URI lors du transfert des données du média.
Exemple :
POST /upload/gmail/v1/users/userId/messages/send
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.
Example :
POST /gmail/v1/users/userId/messages/send
Importation simple
La méthode la plus simple pour importer un fichier consiste à envoyer une simple requête d'importation. Cette option est particulièrement adaptée dans les cas suivants:
- Le fichier est suffisamment petit pour être réimporté dans son intégralité en cas d'échec de la connexion.
- Aucune métadonnée ne doit être envoyée. Cela peut se produire si vous prévoyez d'envoyer des métadonnées pour cette ressource dans une requête distincte, ou si aucune métadonnée n'est compatible ou disponible.
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
Exemple :
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=media
Voici les en-têtes HTTP à utiliser lors d'une requête d'importation simple :
Content-Type
Définissez ce paramètre sur l'un des types de données de média d'importation acceptés par la méthode, comme indiqué dans la documentation de référence de l'API.Content-Length
: spécifiez-y le nombre d'octets que vous importez. Cet en-tête n'est pas requis 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 le paramètre API Gmail.
POST /upload/gmail/v1/users/userId/messages/send?uploadType=media HTTP/1.1 Host: www.googleapis.com Content-Type: message/rfc822 Content-Length: number_of_bytes_in_file Authorization: Bearer your_auth_token Email Message data
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 {
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
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 et ajoutez le paramètre de requête.
uploadType=multipart
, par exemple:
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=multipart
Les en-têtes HTTP de premier niveau à utiliser lors d'une importation en plusieurs parties incluent :
Content-Type
. Défini sur "multipart/related" et incluant la chaîne de délimitation que vous utilisez pour identifier les parties de la requête.Content-Length
. Défini sur le nombre total d'octets dans le corps de la requête. La partie de médias de la requête doit être inférieure à la taille de fichier maximale spécifiée 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 de 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 de médias : doit apparaître en second. La valeur
Content-Type
doit correspondre à l'un des types de média MIME acceptés pour la méthode.
Consultez la documentation de référence de l'API pour obtenir la liste des types MIME de médias acceptés et de limites de taille pour les fichiers importés, pour chaque méthode.
Remarque : Pour créer ou mettre à jour la partie de métadonnées uniquement, sans importer les données associées, envoyez simplement une requête POST
ou PUT
au point de terminaison de la ressource standard : https://www.googleapis.com/gmail/v1/users/userId/messages/send
Exemple : Importation en plusieurs parties
L'exemple ci-dessous illustre une requête d'importation en plusieurs parties pour l'API Gmail.
POST /upload/gmail/v1/users/userId/messages/send?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 {
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
} --foo_bar_baz Content-Type: message/rfc822 Email Message 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 {
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
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 :
- Démarrez une session avec reprise. Effectuez une requête initiale contenant les métadonnées à l'URI d'importation, le cas échéant.
- 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. Envoyez le fichier de médias à l'URI de la session avec reprise.
En outre, les applications qui utilisent l'importation avec reprise doivent posséder un code 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.
Remarque : Une URI d'importation est valable une semaine.
Étape 1 : Démarrez une session avec reprise
Pour lancer une importation avec reprise, envoyez une requête POST
ou PUT
à l'URI /upload de la méthode et ajoutez le paramètre de requête.
uploadType=resumable
, par exemple:
POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable
Le corps de cette requête de lancement doit être vide ou ne contenir que les métadonnées. Vous allez transférer 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 de média MIME des 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 requis si vous utilisez l'encodage de transfert fragmenté.
Consultez la documentation de référence de l'API pour obtenir la liste des types MIME de médias acceptés et de 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 Gmail.
POST /upload/gmail/v1/users/userId/messages/send?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: message/rfc822 X-Upload-Content-Length: 2000000 {
"id": string,
"threadId": string,
"labelIds": [
string
],
"snippet": string,
"historyId": unsigned long,
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
"sizeEstimate": integer,
"raw": bytes
}
Remarque : Pour une requête initiale de mise à jour avec reprise sans métadonnées, ne remplissez pas le corps de la requête et définissez l'en-tête Content-Length
sur 0
.
La section suivante décrit comment gérer la réponse.
Étape 2 : Enregistrez 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/gmail/v1/users/userId/messages/send?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.
Étape 3 : Importez 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 pour télécharger l'intégralité du fichier de messages par e-mail de 2 000 000 octets pour l'exemple actuel.
PUT https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable&upload_id=xa298sd_sdlkj2 HTTP/1.1 Content-Length: 2000000 Content-Type: message/rfc822 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 positive serait 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 un fichier fragmenté
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 aurez peut-être recours à la fragmentation pour réduire la quantité de données transférées dans une seule requête. Cela est utile lorsque le temps imparti à chaque requête est limité pour les requêtes individuelles, comme c'est le cas pour certaines classes de requêtes Google App Engine. Cela 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.
Reprendre une importation interrompue
Si une requête d'importation se termine avant de recevoir une réponse ou si vous recevez une réponse 503 Service Unavailable
du serveur, vous devez reprendre l'importation interrompue. Procédez comme suit :
- Interrogez l'état. 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êteContent-Range
indiquant que la position actuelle dans le fichier est inconnue. Par exemple, définissezContent-Range
sur*/2000000
si la longueur totale de votre fichier correspond à 2 000 000. Si vous ignorez la taille totale du fichier, définissezContent-Range
sur*/*
.Remarque : Vous pouvez interroger l'état entre les fragments, et pas seulement si l'importation est interrompue. Cette opération est utile si vous souhaitez afficher les indications concernant la progression de l'importation pour les navigateurs anciens, par exemple.
- Obtenez 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êteRange
de0-299999
indique que les 300 000 premiers octets du fichier ont été reçus. - Importez 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
Remarque : Il est possible que la réponse d'état soit 201 Created
ou 200 OK
si l'importation est terminée. Cette situation peut se produire si la connexion s'interrompt après l'importation de tous les octets, mais avant que le client ne reçoive une réponse du serveur.
3) 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 en matière de 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 aider à 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
et410 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 en matière 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 :
- Vous envoyez une requête à l'API.
- Vous recevez une réponse
HTTP 503
, qui indique que vous devez relancer la requête. - Vous patientez 1 seconde + "random_number_milliseconds", puis vous relancez la requête.
- Vous recevez une réponse
HTTP 503
, qui indique que vous devez relancer la requête. - Vous patientez 2 secondes + "random_number_milliseconds", puis vous relancez la requête.
- Vous recevez une réponse
HTTP 503
, qui indique que vous devez relancer la requête. - Vous patientez 4 secondes + "random_number_milliseconds", puis vous relancez la requête.
- Vous recevez une réponse
HTTP 503
, qui indique que vous devez relancer la requête. - Vous patientez 8 secondes + "random_number_milliseconds", puis vous relancez la requête.
- Vous recevez une réponse
HTTP 503
, qui indique que vous devez relancer la requête. - Vous patientez 16 secondes + "random_number_milliseconds", puis vous relancez la requête.
- Vous arrêtez, puis vous signalez ou consignez une erreur.
Dans le flux ci-dessus, "random_number_milliseconds" correspond à un nombre aléatoire de millisecondes inférieur ou égal à 1 000. Cette valeur est nécessaire, car l'introduction d'un petit délai aléatoire aide à 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.
Remarque : L'attente correspond toujours à (2 ^ n) + "random_number_milliseconds", où "n" est un entier augmentant de manière monotone défini initialement sur 0. L'entier "n" est augmenté de 1 pour chaque itération (chaque requête).
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.