舊版套裝組合服務的 Blobstore API 總覽

Blobstore API 可讓您的應用程式提供名為「Blob」的資料物件,這類物件會比 Datastore 服務允許的物件大小大上許多。Blob 不僅可用於提供影片或圖片檔等大型檔案外,還可讓使用者上傳大型資料檔案。Blob 的建立方式是透過 HTTP 要求上傳檔案。一般而言,應用程式會向使用者提供具備檔案上傳欄位的表單,藉此執行此操作。提交表單後,Blobstore 會從檔案內容建立 blob 並傳回 blob 的不透明參照,即「blob 鍵」,供您稍後用於提供該 blob。應用程式可根據使用者要求提供完整的 blob 值,或透過類似串流檔案的介面來直接讀取該值。

Blobstore 簡介

App Engine 包含 Blobstore 服務,可讓應用程式提供資料物件,並且只會受到單一 HTTP 連線可上傳或下載資料量的限制。這些物件稱為「Blobstore 值」或「blob」。Blobstore 值會以要求處理常式所傳回的回應提供,並且透過網路表單的上傳作業建立而成。應用程式不會直接建立 blob 資料;相反地,blob 是透過提交網路表單或其他 HTTP POST 要求的方式間接建立。Blobstore 值可提供給使用者,或由應用程式透過 Blobstore API 在類似檔案的串流中存取。

應用程式會提供具備檔案上傳欄位的網路表單,藉此提示使用者上傳 Blobstore 值。應用程式會呼叫 Blobstore API 來產生表單的動作網址。使用者的瀏覽器會透過產生的網址,將檔案直接上傳至 Blobstore。接著 Blobstore 會儲存 blob 並修改要求,讓要求內容包含 blob 金鑰,並且將它傳送至應用程式中的特定路徑。在應用程式中,位於該路徑的要求處理常式可執行額外的表單處理。

為了提供 blob,應用程式會在外送回應中設定標頭,並且由 App Engine 將該回應取代為 blob 值。

Blob 一旦建立後便無法修改,但可予以刪除。每個 blob 在資料儲存庫中都有儲存對應的「blob 資訊記錄」,用以提供有關該 blob 的建立時間與內容類型等詳細資訊。您可以使用 blob 鍵來擷取 blob 資訊記錄並查詢其屬性。

應用程式可透過 API 呼叫,一次讀取 Blobstore 值的其中一個部分。 讀取的部分最大可達 API 傳回值的大小上限。 這個大小略低於 32 MB,在 Java 中會以常數 com.google.appengine.api.blobstore.BlobstoreService.MAX_BLOB_FETCH_SIZE 表示,在 Python 中則以常數 google.appengine.ext.blobstore.MAX_BLOB_FETCH_SIZE 表示。應用程式僅能透過使用者上傳的檔案來建立或修改 Blobstore 值。

使用 Blobstore

應用程式可使用 Blobstore 接受使用者上傳的大型檔案,同時還可以提供這些檔案。檔案上傳之後,就稱為 blob。應用程式不會直接存取 blob,而是透過 blob 資訊實體 (以 BlobInfo 類別表示) 使用 blob。

使用者提交含有一或多個檔案輸入欄位的 HTML 表單就能建立 blob。應用程式會呼叫 使用者提交表單時,使用者的瀏覽器會將指定檔案直接上傳至 Blobstore。Blobstore 會修改使用者要求並儲存上傳的檔案資料,將上傳的檔案資料取代為一或多個對應的 blob 金鑰,接著將修改過的要求傳送至您提供給 blobstore.create_upload_url() 的網址路徑所在的處理常式。

這個處理常式可根據 blob 鍵執行額外的處理工作。

應用程式可以透過類似檔案的串流介面讀取一部分的 Blobstore 值, 類似檔案的串流介面。請參閱 BlobReader 類別。

上傳 blob

如要建立並上傳 blob,請依照下列程序執行:

1. 建立上傳網址

呼叫 blobstore.create_upload_url() 以建立使用者所填寫表單的上傳網址,在表單的 POST 完成時傳送要載入的應用程式路徑。

upload_url = blobstore.create_upload_url("/upload_photo")

非同步版本為 create_upload_url_async()。此版本可讓應用程式的程式碼在 Blobstore 產生上傳網址時繼續執行。

2. 建立上傳表單

表單必須包含檔案上傳欄位,且表單的 enctype 必須設為 multipart/form-data。使用者提交表單時,POST 將由建立 blob 的 Blobstore API 來處理。這個 API 另外也會建立 blob 的資訊記錄並儲存在 Datastore 中,然後將修改過的要求以 blob 金鑰的形式傳送至應用程式中的指定路徑。

您必須提供 Content-Typetext/html; charset=utf-8 的表單頁面,否則系統會以錯誤的方式解譯任何含有非 ASCII 字元的檔案名稱。
由於 Python 3 適用的 Blobstore 不會使用 webapp,您必須自行設定 Content-Type,防止網路架構設定預設內容類型,以及 App Engine 將此類型設為推測類型。

您無法使用無伺服器 NEG 搭配全域外部應用程式負載平衡器,處理傳送至 blobstore.create_upload_url 呼叫傳回的 /_ah/upload/ URL 的上傳要求。您必須改為將這些上傳要求直接轉送至 App Engine 服務。您可以透過 appspot.com 網域或直接對應至 App Engine 服務的自訂網域,執行這項操作。

3. 實作上傳處理常式

在這個處理常式中,您可以將 blob 鍵與應用程式資料模型的其他部分儲存在一起。blob 鍵本身仍可從資料儲存庫中的 blob 資訊實體存取。請注意,在使用者提交表單並呼叫處理常式後,blob 就已經儲存,而 blob 資訊也已新增至 Datastore。如果應用程式不想保留 blob,您應立即刪除 blob,以防止 blob 成為孤立檔案。

對於所有 Flask 應用程式,對 BlobstoreUploadHandler 類別中方法的所有呼叫,都需要 request.environ dictionary (從 Flask 模組匯入的要求)。如果您的應用程式是沒有 Web 架構的 WSGI 應用程式,請使用 get_uploads() 方法中的 environ 參數。 修改使用者要求時,Blobstore 會清空已上傳檔案中的 MIME 區塊,然後以 MIME 區塊標頭的形式加入 blob 金鑰。Blobstore 會保留所有其他表單欄位和部分,並傳送至上傳處理常式。如果您未指定內容類型,Blobstore 會嘗試從副檔名推論。如果無法判斷內容類型,系統會為新建的 blob 指派內容類型 application/octet-stream

提供 blob

如要提供 blob,您必須以應用程式路徑的形式加入 blob 下載處理常式。 應用程式會在連出回應中設定標頭,藉此提供 blob。如果使用 Flask,BlobstoreDownloadHandler 類別需要 request.environ 字典 (要求是從 Flask 模組匯入)。如果您的應用程式是沒有網路架構的 WSGI 應用程式,請在 send_blob() 方法中使用 environ 參數

Blob 可透過任何應用程式網址提供。如要在應用程式中提供 blob,請在包含 blob 鍵的回應中放上特殊標頭。App Engine 會以 blob 的內容取代回應的本文。

Blob 位元組範圍

Blobstore 可根據要求,提供某個極大值的一部分,而非完整的值。如要提供部分值,請在外送回應中加入 X-AppEngine-BlobRange 標頭。此標頭的值代表標準的 HTTP 位元組範圍。位元組編號從零開始。空白的 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 不支援在單一要求中提供多個位元組範圍 (例如 100-199,200-299),即便範圍重複也一樣。

完整的應用程式範例

請參閱 Python 3 適用的 Blobstore API 指南中的 Flask 應用程式範例。

使用圖片服務與 Blobstore

圖片服務可將 Blobstore 值做為轉換的來源。來源圖片的大小可達 Blobstore 值的上限大小。圖片服務仍會將轉換後的圖片傳回應用程式,因此轉換後的圖片必須小於 32 MB。這很適合用於建立由使用者上傳的大型相片縮圖。如要瞭解如何將圖片服務與 Blobstore 值搭配使用,請參閱 圖片服務說明文件

使用 Blobstore API 與 Cloud Storage

您可以使用 Blobstore API,將 blob 儲存至 Cloud Storage,而非儲存在 Blobstore。您必須按照 Cloud Storage 說明文件設定值區,並在 blobstore.create_upload_url gs_bucket_name 參數。

在上傳處理常式中,您需要處理傳回的 FileInfo 中繼資料 ,並明確儲存稍後用於擷取 blob 的 Cloud Storage 檔案名稱。

您也可以使用 Blobstore API 提供 Cloud Storage 物件。

如要使用更現代的物件儲存空間解決方案,請考慮從 App Engine Blobstore 遷移至 Cloud Storage

使用 BlobReader

應用程式可以透過類似於 Python file 物件的介面讀取 Blobstore 值的資料。這個介面可讀取任何位元組位置開始的值,並可使用多重服務呼叫與緩衝作業,因此即使受到單次服務呼叫回應的大小限制,應用程式還是可以存取該值的完整大小。

BlobReader 類別可以將下列三個值當中的其中一個當做其建構函式的引數:

物件會採用常見的檔案方法來讀取該值。應用程式無法修改 Blobstore 值,因為系統未實作檔案寫入方法。

# Instantiate a BlobReader for a given Blobstore blob_key.
blob_reader = blobstore.BlobReader(blob_key)

# Instantiate a BlobReader for a given Blobstore blob_key, setting the
# buffer size to 1 MB.
blob_reader = blobstore.BlobReader(blob_key, buffer_size=1048576)

# Instantiate a BlobReader for a given Blobstore blob_key, setting the
# initial read position.
blob_reader = blobstore.BlobReader(blob_key, position=0)

# Read the entire value into memory. This may take a while depending
# on the size of the value and the size of the read buffer, and is not
# recommended for large values.
blob_reader_data = blob_reader.read()

# Write the contents to the response.
self.response.headers["Content-Type"] = "text/plain"
self.response.write(blob_reader_data)

# Set the read position back to 0, then read and write 3 bytes.
blob_reader.seek(0)
blob_reader_data = blob_reader.read(3)
self.response.write(blob_reader_data)
self.response.write("\n")

# Set the read position back to 0, then read and write one line (up to
# and including a '\n' character) at a time.
blob_reader.seek(0)
for line in blob_reader:
    self.response.write(line)

提出非同步要求

應用程式可以呼叫在背景執行的 Blobstore 函式。Blobstore 執行要求時,應用程式能夠執行其他工作。如要提出要求,應用程式會呼叫非同步函式。函式會立即傳回遠端程序呼叫 (RPC) 物件,這個物件代表了該項要求。應用程式需要要求的結果時,會呼叫 RPC 物件的 get_result() 方法。

如果應用程式呼叫 get_result() 時,服務尚未完成要求,方法會等到要求完成 (或達到期限,或發生錯誤) 為止。這個方法會傳回結果物件,或在執行要求時發生錯誤時發出例外狀況。舉例來說,這個程式碼片段

upload_url = blobstore.create_upload_url('/upload')
slow_operation()
self.response.out.write("""<form action="%s" method="POST"
                           enctype="multipart/form-data">""" % upload_url)

會變成:

upload_url_rpc = blobstore.create_upload_url_async('/upload')
slow_operation()
upload_url = upload_url_rpc.get_result()
self.response.out.write("""<form action="%s" method="POST"
                           enctype="multipart/form-data">""" % upload_url)

在本範例中,應用程式會在 Blobstore 產生上傳網址的同時,執行 slow_operation() 程式碼。

配額與限制

Blobstore 值所使用的空間會佔用「儲存資料 (可計費)」配額。資料儲存庫中的 Blob 資訊實體會計入資料儲存庫相關的限額中。請注意,Cloud Storage 屬付費使用服務,您需按照 Cloud Storage 價目表支付費用。

如要進一步瞭解整個系統的安全配額,請參閱配額

除了整個系統的安全配額外,Blobstore 的使用配額還受到下列特別限制:

  • 應用程式透過單一 API 呼叫可讀取的 Blobstore 資料量上限為 32 MB。
  • 單一表單 POST 可上傳的檔案數量上限為 500 個。