添付ファイルをアップロードしています

Gmail API を使用すると、下書き作成または更新するときや、メッセージを挿入または送信するときにファイルデータをアップロードできます。

アップロード オプション

Gmail API を使用すると、特定のタイプのバイナリデータ(メディア)をアップロードできます。アップロードできるデータの性質については、メディア アップロードをサポートするメソッドのリファレンス ページをご覧ください。

  • 最大アップロード ファイルサイズ: このメソッドで保存できるデータの最大量。
  • 受け入れ可能なメディア MIME タイプ: このメソッドで保存できるバイナリデータの種類。

次のいずれかの方法でアップロードをリクエストできます。使用するメソッドは、uploadType リクエスト パラメータで指定します。

  • シンプル アップロードuploadType=media)。比較的小さいファイル(例: 5 MB 以下)を高速で転送します。
  • マルチパート アップロードuploadType=multipart)。比較的小さいファイルとメタデータを高速転送します。ファイルおよびそれを記述するメタデータが、1 つのリクエストですべて転送されます。
  • 再開可能なアップロード: uploadType=resumable。信頼性の高い転送で、特に、比較的大きいファイルで使用されます。このメソッドでは、セッション開始リクエストを使用します。オプションでメタデータを含めることができます。この方法は小さいファイルでも機能します(アップロードごとに HTTP リクエストが 1 つ追加されます)。したがって、ほとんどのアプリケーションでこれを使用できます。

メディアをアップロードするときは、特別な URI を使用します。実際、メディア アップロードをサポートする方法では、次の 2 つの URI エンドポイントがあります。

  • /upload URI。メディアに使用されます。アップロード エンドポイントの形式は、標準リソース URI に「/upload」接頭辞を付けたものです。この URI は、メディアデータそのものを転送するときに使用します。

    例: POST /upload/gmail/v1/users/userId/messages/send

  • メタデータの場合、標準リソース URI。リソースにデータ フィールドが含まれている場合、これらのフィールドは、アップロードするファイルを記述するメタデータの保管に使用されます。この URI は、メタデータ値の作成または更新の際に使用できます。

    例: POST /gmail/v1/users/userId/messages/send

シンプル アップロード

ファイルをアップロードする最も簡単な方法は、シンプル アップロード リクエストを行うことです。このオプションは、次のような場合に適しています。

  • ファイルが小さく、接続が失敗したときはファイル全体を再度アップロードできる場合。
  • 送信するメタデータがない場合。たとえば、このリソースのメタデータを別のリクエストで送信することを予定している場合や、メタデータがサポートされていないか利用できない場合などです。

シンプル アップロードを使用するには、アップロード方法の /upload URI への POST リクエストまたは PUT リクエストを作成し、クエリ パラメータ uploadType=media を追加します。例:

POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=media

シンプル アップロード リクエストの作成時に使用する HTTP ヘッダーの内容は次のとおりです。

  • Content-Type: アップロード方法で使用可能なアップロード メディア データタイプのいずれかに設定します(API リファレンスをご覧ください)。
  • Content-Length: アップロードするバイト数に設定します。チャンク形式転送エンコードを使用する場合は不要です。

例: シンプル アップロード

Gmail API でのシンプル アップロード リクエストの使用例を次に示します。

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

リクエストが成功すると、HTTP ステータス コード 200 OK がメタデータとともにサーバーから返されます。

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
}

マルチパート アップロード

アップロードするデータとともにメタデータを送信する場合は、1 つの multipart/related リクエストを作成できます。これは、送信するデータが小さく、接続が失敗しても全体を再アップロードできる場合に適しています。

マルチパート アップロードを使用するには、アップロード方法の /upload URI への POST リクエストまたは PUT リクエストを作成し、クエリ パラメータ uploadType=multipart を追加します。次に例を示します。

POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=multipart

マルチパート アップロード リクエストを作成するときに使用する最上位 HTTP ヘッダーには、以下を含めます。

  • Content-Type。これを multipart/related に設定し、リクエストの各部分の識別に使用する境界文字列を含めます。
  • Content-Length。リクエスト本文の合計バイト数を設定します。リクエストのメディア部分は、このメソッドに関して指定された最大ファイルサイズより小さくなければなりません。

リクエスト本文の形式は multipart/related コンテンツ タイプ [RFC2387] となり、必ず 2 つの部分が含まれます。各部分は境界文字列で区別され、最後の境界文字列には後に 2 つのハイフンが続きます。

マルチパート リクエストの各部分には、次の Content-Type ヘッダーを追加する必要があります。

  1. メタデータ部分: 最初に配置する必要があります。Content-Type は、受け入れ可能なメタデータ形式のいずれかと一致する必要があります。
  2. メディア部分: 2 番目に配置する必要があります。Content-Type は、メソッドで受け入れ可能なメディア MIME タイプのいずれかと一致する必要があります。

各メソッドで使用できるメディア MIME タイプと、アップロードできるファイルのサイズの上限については、API リファレンスをご覧ください。

注: 関連付けられたデータをアップロードせずに、メタデータ部分のみを生成または更新するには、単に POST または PUT リクエストを標準リソース エンドポイント(https://www.googleapis.com/gmail/v1/users/userId/messages/send)に送信します。

例: マルチパート アップロード

Gmail API でのマルチパート アップロード リクエストの例を次に示します。

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

リクエストが成功すると、HTTP 200 OK ステータス コードとメタデータがサーバーから返されます。

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
}

再開可能なアップロード

より信頼性の高い方法でデータファイルをアップロードするには、再開可能なアップロード プロトコルを使用します。このプロトコルを使用すると、通信障害によってデータのフローが中断しても、その後アップロード オペレーションを再開できます。この方法は特に、大容量のファイルを転送するときや、モバイル クライアント アプリからのアップロードなどでネットワークの中断やその他の送信エラーが起こる可能性が高いときに役立ちます。また、ネットワーク障害が発生した場合に大容量のファイルのアップロードを最初からやり直す必要がなくなり、使用する帯域幅を削減できます。

再開可能なアップロードを使用する手順は、以下のとおりです。

  1. 再開可能なセッションを開始します。アップロード URI(メタデータがある場合は、メタデータを含むアップロード URI)に対する最初のリクエストを作成します。
  2. 再開可能なセッション URI を保存します。最初のリクエストのレスポンスで返されるセッション URI を保存します。この URI をこのセッションの他のリクエストで使用します。
  3. ファイルをアップロードします。再開可能なセッション URI にメディア ファイルを送信します。

また、再開可能なアップロードを使用するアプリには、中断したアップロードを再開するためのコードが必要です。アップロードが中断した場合、正常に受信されたデータの量を判別し、そのポイントからアップロードを再開します。

注: アップロード URI の有効期間は 1 週間です。

手順 1: 再開可能なセッションを開始する

再開可能アップロードを開始するには、アップロード方法の /upload URI への POST リクエストまたは PUT リクエストを作成し、クエリ パラメータ uploadType=resumable を追加します。次に例を示します。

POST https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send?uploadType=resumable

この最初のリクエストでは、本文は空またはメタデータのみのいずれかです。アップロードするファイルの実際の内容は後続のリクエストで転送します。

最初のリクエストでは次の HTTP ヘッダーを使用します。

  • X-Upload-Content-Type。後続のリクエストで転送するアップロード データのメディア MIME タイプを設定します。
  • X-Upload-Content-Length。後続のリクエストで転送するアップロード データのバイト数を設定します。このリクエストの時点で長さが不明な場合は、このヘッダーを省略できます。
  • メタデータを提供する場合: Content-Type。メタデータのデータ型に応じて設定します。
  • Content-Length。最初のリクエストの本文で提供するバイト数を設定します。チャンク形式転送エンコードを使用する場合は不要です。

各メソッドで使用できるメディア MIME タイプと、アップロードできるファイルのサイズの上限については、API リファレンスをご覧ください。

例: 再開可能なセッション開始リクエスト

次の例は、Gmail API で再開可能セッションを開始する方法を示しています。

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
}

注: 最初の再開可能な更新リクエストをメタデータなしで発行する場合は、リクエスト本文を空のままにして、Content-Length ヘッダーを 0 に設定します。

次に、レスポンスを処理する方法を説明します。

手順 2:再開可能なセッション URI を保存する

セッション開始リクエストが成功すると、API サーバーは HTTP ステータス コード 200 OK のレスポンスを返します。また、再開可能なセッション URI を指定した Location ヘッダーも返します。下の例に示されている Location ヘッダーには、このセッションで使用する一意のアップロード ID を指定した upload_id クエリ パラメータ部分が含まれています。

例: 再開可能なセッション開始のレスポンス

手順 1 のリクエストに対するレスポンスは次のとおりです。

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

上のレスポンス例に示されている Location ヘッダーの値は、実際にファイルをアップロードするとき、またはアップロード ステータスを照会するときに HTTP エンドポイントとして使用するセッション URI です。

後続のリクエストで使用できるように、このセッション URI をコピーして保存します。

手順 3: ファイルをアップロードする

ファイルをアップロードするには、前の手順で取得したアップロード URI に PUT リクエストを送信します。アップロード リクエストの形式は次のとおりです。

PUT session_uri

再開可能なファイル アップロードのリクエストを作成するときに使用する HTTP ヘッダーには、Content-Length を含めます。このフィールドに、このリクエストでアップロードするバイト数(通常はアップロード ファイルのサイズ)を設定します。

例: 再開可能なファイル アップロード リクエスト

この例で 2,000,000 バイトのメール メッセージ ファイル全体をアップロードする再開可能なリクエストは次のとおりです。

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

リクエストが成功すると、サーバーは HTTP 201 Created のレスポンスを、このリソースに関連付けられているメタデータとともに返します。再開可能なセッションの最初のリクエストが PUT だった場合、既存のリソースを更新したときの成功のレスポンスは 200 OK となり、このリソースに関連付けられているメタデータが返されます。

アップロード リクエストが中断された場合や、サーバーから HTTP 503 Service Unavailable などの 5xx レスポンスが返された場合は、中断されたアップロードを再開するに記載された手順に従ってください。 


チャンク形式でファイルをアップロードする

再開可能なアップロードでは、ファイルをチャンクに分割して、各チャンクを順にアップロードする一連のリクエストを送信できます。追加のリクエストに付随してパフォーマンス コストが発生するため、この方法は推奨されず、通常は不要です。ただし、1 つのリクエストで転送するデータの量を減らすために、チャンクの使用が必要になることもあります。Google App Engine リクエストの一部のクラスのように、リクエストごとに固定の時間制限がある場合は、この方法が役立ちます。また、たとえばデフォルトでアップロードの進捗表示をサポートしていない古いブラウザに、アップロードの進捗インジケーターを表示することもできます。


中断されたアップロードを再開する

レスポンスを受信する前にアップロード リクエストが終了した場合や、サーバーから HTTP 503 Service Unavailable レスポンスが返された場合は、中断されたアップロードを再開する必要があります。方法は次のとおりです。

  1. ステータスをリクエストする。空の PUT リクエストをアップロード URI に発行して、アップロードの現在のステータスを照会します。このリクエストの HTTP ヘッダーには、ファイルの現在の位置が不明であることを示す Content-Range ヘッダーを含める必要があります。たとえば、ファイルの合計サイズが 2,000,000 の場合、Content-Range*/2000000 に設定します。ファイル全体のサイズがわからない場合は、Content-Range*/* に設定します。

    注: アップロードが中断された場合でなくても、チャンク間のステータスをリクエストできます。これは、たとえば古いブラウザにアップロードの進捗インジケーターを表示する場合に役立ちます。

  2. アップロードされたバイト数を取得する。ステータス クエリからのレスポンスを処理します。サーバーはレスポンスの Range ヘッダーを使用して、その時点までに何バイト受信したかを示します。たとえば、Range ヘッダーが 0-299999 の場合、ファイルの先頭から 300,000 バイトを受信したという意味になります。
  3. 残りのデータをアップロードする。最後に、リクエストを再開する位置を確認して、残りのデータまたは現在のチャンクを送信します。どちらの場合も、残りのデータを独立したチャンクとして扱う必要があります。つまり、アップロードを再開するときに Content-Range ヘッダーを送信する必要があります。
例: 中断されたアップロードを再開する

1)アップロード ステータスをリクエストします。

次のリクエストでは、Content-Range ヘッダーを使用して、2,000,000 バイトのファイルで現在の位置が不明であることを示しています。

PUT {session_uri} HTTP/1.1
Content-Length: 0
Content-Range: bytes */2000000

2)レスポンスから、これまでにアップロードされたバイト数を抽出します。

サーバーのレスポンスの Range ヘッダーは、これまでにファイルの先頭の 43 バイトを受信したことを示しています。Range ヘッダーの上限値を使用して、再開可能なアップロードを開始する位置を決定します。

HTTP/1.1 308 Resume Incomplete
Content-Length: 0
Range: 0-42

注: アップロードが完了している場合、ステータスのレスポンスが 201 Created または 200 OK になることがあります。このような状況は、すべてのバイトがアップロードされた後、クライアントがサーバーからレスポンスを受信する前に接続が切断された場合に発生します。

3)中断された位置からアップロードを再開します。

次のリクエストは、ファイルの 43 番目以降の残りのバイトを送信して、アップロードを再開します。

PUT {session_uri} HTTP/1.1
Content-Length: 1999957
Content-Range: bytes 43-1999999/2000000

bytes 43-1999999

ベスト プラクティス

メディアをアップロードするときは、エラー処理に関連するいくつかのおすすめの方法を知っておくと便利です。

  • 接続の中断や次のような 5xx エラーが原因で失敗したアップロードは、再開または再試行してください。
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • アップロードの再開または再試行のリクエスト時に 5xx サーバーエラーが返された場合は、指数バックオフ戦略を使用します。こうしたエラーは、サーバーに負荷がかかりすぎているときに発生することがあります。指数バックオフは、大量のリクエストまたは大量のネットワーク トラフィックが発生しているときに、この種の問題の軽減に役立ちます。
  • その他の種類のリクエストでは指数バックオフは使用できませんが、何度か再試行できます。リクエストを再試行するときは、再試行の回数を制限します。たとえば、コードで再試行の回数を 10 回までに制限して、それを超えるとエラーが報告されるようにできます。
  • 再開可能なアップロードで 404 Not Found または 410 Gone エラーが発生した場合には、最初から全体のアップロードをやり直します。

指数バックオフ

指数バックオフは、ネットワーク アプリケーションの標準的なエラー処理方法で、クライアントはリクエスト間の遅延を増加させながら、失敗したリクエストを定期的に再試行します。大量のリクエストまたは大量のネットワーク トラフィックが原因でサーバーがエラーを返した場合、指数バックオフはこのようなエラーの処理に適した方法です。逆に、承認認証情報が無効である、ファイルが見つからないなど、ネットワークのボリュームまたはレスポンス タイムに関係のないエラーの処理には適していません。

指数バックオフを適切に使用すると、帯域幅の使用効率が高くなり、より少ないリクエスト数で正常なレスポンスを受け取ることができ、同時実行環境でのリクエストのスループットが最大化します。

シンプルな指数バックオフを実装するフローは次のとおりです。

  1. API へのリクエストを作成します。
  2. リクエストの再試行が必要であることを示す HTTP 503 レスポンスを受信します。
  3. 1 秒 + random_number_milliseconds の間待機してから、リクエストを再試行します。
  4. リクエストの再試行が必要であることを示す HTTP 503 レスポンスを受信します。
  5. 2 秒 + random_number_milliseconds の間待機してから、リクエストを再試行します。
  6. リクエストの再試行が必要であることを示す HTTP 503 レスポンスを受信します。
  7. 4 秒 + random_number_milliseconds の間待機してから、リクエストを再試行します。
  8. リクエストの再試行が必要であることを示す HTTP 503 レスポンスを受信します。
  9. 8 秒 + random_number_milliseconds の間待機してから、リクエストを再試行します。
  10. リクエストの再試行が必要であることを示す HTTP 503 レスポンスを受信します。
  11. 16 秒 + random_number_milliseconds の間待機してから、リクエストを再試行します。
  12. フローを停止します。エラーをレポートまたはログに記録します。

上記のフローで、random_number_milliseconds は、1,000 ミリ秒以下の乱数です。この乱数は、ランダムな短い遅延を発生させることで負荷をより均等に分散し、サーバーの暴走を防ぐために必要です。random_number_milliseconds の値は、待機するたびに再定義する必要があります。

注: 待機時間は常に (2 ^ n) + random_number_milliseconds(n は 0 から始まる単調増加整数)です。整数 n は、繰り返し(リクエスト)のたびに 1 ずつ増えます。

このアルゴリズムは、n が 5 になると終了するように設定されています。この上限によって、クライアントが無限に再試行を繰り返すことを防ぎます。総遅延時間が約 32 秒になると、リクエストは「回復不能なエラー」と判断されます。再試行の最大回数を増やすこともできますが(特に、長いアップロードを行う場合)、再試行の遅延時間には合理的な上限(1 分以内など)を設定してください。

API クライアント ライブラリ ガイド