以前のバンドル サービス用の Blobstore API の概要

Blobstore API を使用すると、blob と呼ばれるデータ オブジェクトをアプリケーションで提供できるようになります。blob は、Datastore サービスのオブジェクトに許可されているサイズよりはるかに大きいサイズのオブジェクトです。blob は、動画や画像などのサイズの大きいファイルを提供する場合や、ユーザーがサイズの大きいデータファイルをアップロードする場合に便利です。blob は HTTP リクエストでファイルをアップロードすることによって作成されます。通常アプリケーションでこの処理を行うには、ファイル アップロード用のフィールドを含むフォームをユーザーに提示します。フォームが送信されると、Blobstore によってファイルの内容から blob が作成され、blob への不透明な参照(blob キー)が返されます。このキーは後で blob を提供するときに使用できます。アプリケーションは、ユーザー リクエストに応じて完全な blob 値を提供でき、あるいはファイルに似たストリーミング インターフェースを使用して、値を直接読み取ることができます。

Blobstore を導入する

App Engine には Blobstore サービスが含まれています。このサービスを利用すると、アプリケーションでデータ オブジェクトを提供できます。制限は 1 回の HTTP 接続でアップロードまたはダウンロードできるデータ量のみです。これらのオブジェクトを Blobstore 値または blob と呼びます。Blobstore 値はリクエスト ハンドラからのレスポンスとして提供され、ウェブフォームを通じたアップロード データとして作成されます。blob データは、アプリケーションで直接作成されるのではなく、送信されたウェブフォームや他の HTTP POST リクエストによって間接的に作成されます。Blobstore API を使用すると、Blobstore 値をユーザーに送信することや、ファイルに似たストリームでアプリケーションから Blobstore 値にアクセスできます。

アプリケーションで Blobstore 値のアップロードをユーザーに促すには、ファイル アップロード用のフィールドを含むウェブフォームを提示します。アプリケーションは、Blobstore API を呼び出してフォームのアクション URL を生成します。ユーザーのブラウザは、生成された URL を通じてファイルを Blobstore に直接アップロードします。次に、Blobstore は blob を保存し、blob キーが含まれるようにリクエストを書き換えて、アプリケーションのパスに渡します。そのパスにはアプリケーションのリクエスト ハンドラがあり、そこで追加のフォーム処理を行うことができます。

blob を提供するには、アプリケーションで送信レスポンスにヘッダーを設定します。このレスポンスは App Engine で blob 値に置き換えられます。

作成した blob は変更できませんが、削除することはできます。各 blob には対応する blob 情報レコードがあり、データストアに保存されています。blob 情報レコードを参照すると、作成日時やコンテンツ タイプなどの blob の詳細がわかります。blob キーを使用して blob 情報レコードをフェッチし、そのプロパティへのクエリができます。

Blobstore を使用する

Blobstore を使用すると、ユーザーからアップロードされるサイズの大きなファイルをアプリケーションで受け取ることや提供することができます。アップロードされたファイルは blob と呼ばれます。アプリケーションが ファイル名を使用して直接 blob にアクセスすることはありません。代わりに、appengine.BlobKey タイプで blob を参照します。クラスで表される)Datastore の blob 情報エンティティを介して blob を操作します。

ユーザーは 1 つ以上のファイル入力フィールドを含む HTML フォームを送信して blob を作成します。アプリケーションは、このフォームの宛先(アクション)としてblobstore.UploadURLを設定します。 この関数には、アプリケーションのハンドラの URL パスを渡します。ユーザーがフォームを送信すると、指定されたファイルがユーザーのブラウザから Blobstore に直接アップロードされます。Blobstore はユーザーのリクエストを書き換え、アップロードされたファイルデータを保存します。その際、アップロードされたファイルデータを 1 つ以上の対応する blob キーで置き換えます。その後、書き換えたリクエストを、blobstore.UploadURLに指定された URL パスにあるハンドラに渡します。

このハンドラは、blob キーに基づいて追加の処理を行えます。 最後に、ハンドラはヘッダーのみのリダイレクト レスポンス(301、302、または 303)を返す必要があります。ブラウザは通常、blob アップロードのステータスを示す別のページにリダイレクトされます。

アプリケーションは、Blobstore 値の一部を読み取るために blobstore.Reader を使用します。

blob をアップロードする

blob を作成してアップロードする手順は次のとおりです。

1. アップロード URL を作成する

blobstore.UploadURLを呼び出して、ユーザーが記入するフォームのアップロード URL を作成し、そのフォームの POST が完了したときに読み込むアプリケーション パスを渡します。

ctx := appengine.NewContext(r)
uploadURL, err := blobstore.UploadURL(ctx, "/upload", nil)
if err != nil {
	serveError(ctx, w, err)
	return
}

2. アップロード フォームを作成する

フォームにはファイル アップロード用のフィールドを含め、フォームの enctypemultipart/form-data と設定する必要があります。ユーザーがフォームを送信すると、Blobstore API が POST を処理し、blob を作成します。この API はさらに、blob の情報レコードを作成してデータストアに保存し、指定されたパスにあるアプリケーションに、blob キーに書き換えたリクエストを渡します。

	var rootTemplate = template.Must(template.New("root").Parse(rootTemplateHTML))

	const rootTemplateHTML = `
<html><body>
<form action="{{.}}" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file"><br>
<input type="submit" name="submit" value="Submit">
</form></body></html>
`

フォームのページは Content-Typetext/html; charset=utf-8 を指定して提供する必要があります。そうしないと、ASCII 以外の文字を使用したファイル名が誤って解釈されます。
これは Go のデフォルトのコンテンツ タイプですが、独自の Content-Type を設定する場合はこの点に留意する必要があります。

サーバーレス NEG を使用するグローバル外部アプリケーション ロードバランサを使用して、blobstore.create_upload_url 呼び出しから返された /_ah/upload/ URL に送信されたアップロード リクエストを処理することはできません。代わりに、これらのアップロード リクエストを App Engine サービスに直接ルーティングする必要があります。これを行うには、appspot.com ドメインまたは App Engine サービスに直接マッピングされたカスタム ドメインを使用します。

3. アップロード ハンドラを実装する

このハンドラでは、blob キーとともにアプリケーションのデータモデルの残りの部分を保存できます。blob キー自体には、Datastore の blob 情報エンティティから引き続きアクセスできます。ユーザーがフォームを送信し、ハンドラが呼び出された時点で、blob はすでに保存され、blob 情報が Datastore に追加されていることに注意してください。アプリケーションに blob を保持しない場合は、すぐに blob を削除して blob が孤立しないようにしてください。

ctx := appengine.NewContext(r)
blobs, _, err := blobstore.ParseUpload(r)
if err != nil {
	serveError(ctx, w, err)
	return
}
file := blobs["file"]
if len(file) == 0 {
	log.Errorf(ctx, "no file uploaded")
	http.Redirect(w, r, "/", http.StatusFound)
	return
}
http.Redirect(w, r, "/serve/?blobKey="+string(file[0].BlobKey), http.StatusFound)
ユーザーのリクエストを書き換えるとき、Blobstore はアップロードされたファイルの MIME パーツを空にして、blob キーを MIME パーツのヘッダーとして追加します。他のすべてのフォーム フィールドとパーツは保持され、アップロード ハンドラに渡されます。コンテンツ タイプを指定していない場合、Blobstore はファイル拡張子から推定を試みます。コンテンツ タイプを判断できない場合は、新しく作成された blob にコンテンツ タイプ application/octet-stream を割り当てます。

blob を提供する

blob を提供するには、blob のダウンロード ハンドラをパスとしてアプリケーションに含める必要があります。 このハンドラは、目的の blob の blob キーを blobstore.Send に渡す必要があります。 この例では、ダウンロードされたハンドラに blob キーがURL 引数 r.FormValue("blobKey") として渡されます。 実際のダウンロード ハンドラでは、他のメソッドやユーザーの操作など任意の手段で blob キーを取得できます。

blobstore.Send(w, appengine.BlobKey(r.FormValue("blobKey")))

blob は、任意のアプリケーション URL から提供できます。アプリケーションで blob を提供するには、blob キーを含むレスポンスに特別なヘッダーを配置します。App Engine はレスポンスの本文を blob のコンテンツに置き換えます。

blob バイト範囲

Blobstore は、リクエストへのレスポンスとして、サイズの大きな値全体ではなく値の一部の提供をサポートしています。値の一部を提供するには、送信レスポンスに X-AppEngine-BlobRange ヘッダーを含めます。その値は標準的な HTTP バイト範囲とします。バイト番号は 0 から始まります。X-AppEngine-BlobRange を空にすると、API は範囲ヘッダーを無視して blob 全体を提供します。範囲の例を以下に示します。

  • 0-499: 値の最初の 500 バイト(0~499 バイト目まで)を提供します。
  • 500-999: 501 バイト目から始まる 500 バイトを提供します。
  • 500-: 501 バイト目から値の最後までのすべてのバイトを提供します。
  • -500: 値の最後の 500 バイトを提供します。

Blobstore 値に対して有効なバイト範囲が指定されている場合、Blobstore は 206 Partial Content ステータス コードとリクエストされたバイト範囲をクライアントに送信します。範囲が有効でなければ、Blobstore は 416 Requested Range Not Satisfiable を送信します。

Blobstore では、重複の有無にかかわらず、1 回のリクエストで複数のバイト範囲の指定(100-199,200-299 など)を行うことはできません。

サンプル アプリケーションを完成させる

Go 1.11 のデモアプリは GitHub で入手できます。古い Blobstore パッケージ名には /v2/ を挿入する必要があります。

Cloud Storage で Blobstore API を使用する

Blobstore API を使用して Blobstore ではなく Cloud Storage に blob を保存できます。Cloud Storage のドキュメントの説明に従ってバケットを設定し、そのバケットとファイル名をUploadURL 関数の UploadURLOptions に指定する必要があります。

アップロード ハンドラで、必要な返された blob のマップを処理し、あとで blob の取得で必要になる Cloud Storage のファイル名を明示的に格納する必要があります。

Blobstore API を使用して Cloud Storage オブジェクトを提供することもできます。

Cloud Storage オブジェクトを提供するには、blob を提供するで説明しているように、BlobKeyForFile を使用して必要な blobkey を生成します。

割り当てと上限

Blobstore 値に使用する領域は、保存データ(課金対象)の割り当て量の計算対象になります。Datastore の blob 情報エンティティは Datastore 関連の制限に対してカウントされます。なお、Cloud Storage は従量課金サービスであり、Cloud Storage の価格表に従って課金されることに注意してください。

システム全体の安全上の割り当て量について詳しくは、割り当てをご覧ください。

Blobstore の使用については特に、システム全体の安全上の割り当て量に加えて次の制限が適用されます。

  • アプリケーションからの API 呼び出し 1 回で読み取ることのできる Blobstore データの最大サイズは 32 MB です。
  • 1 つのフォームの POST でアップロードできるファイルの最大数は 500 です。
こうしたサイズ制限を回避する方法については、Send 関数のドキュメントをご覧ください。