Java 8 適用的 Blobstore API 總覽

注意事項:建議您透過 Google Cloud Storage (而非 Blobstore) 儲存 blob 資料。

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

Blobstore 簡介

Google 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 表示。應用程式如要建立或修改 Blobstore 值,必須由使用者上傳檔案。

使用 Blobstore

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

使用者提交含有一或多個檔案輸入欄位的 HTML 表單就能建立 blob。應用程式會將 blobstoreService.createUploadUrl() 設為此表單的目的地 (動作),並將應用程式中處理常式的網址路徑傳送給函式。使用者提交表單時,使用者的瀏覽器會將指定檔案直接上傳至 Blobstore。Blobstore 會修改使用者要求並儲存上傳的檔案資料,將上傳的檔案資料取代為一或多個對應的 blob 金鑰,接著將修改過的要求傳送至您提供給 blobstoreService.createUploadUrl() 的網址路徑上的處理常式。這個處理常式可根據 blob 金鑰執行額外的處理工作。

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

上傳 blob

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

1. 建立上傳網址

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

<body>
    <form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
        <input type="file" name="myFile">
        <input type="submit" value="Submit">
    </form>
</body>

請注意,如果上傳表單是以 JSP 建立,則會以上述格式顯示。

2. 建立上傳表單

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

3. 實作上傳處理常式

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

在下列程式碼中,getUploads 會傳回一組已上傳的 blob。Map 物件是一份清單,會在上傳欄位的名稱與欄位中的 blob 之間建立關聯。

Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");

if (blobKeys == null || blobKeys.isEmpty()) {
    res.sendRedirect("/");
} else {
    res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
}

Blobstore 修改使用者要求時,系統會清空已上傳檔案中的 MIME 區塊的主體內容,然後以 MIME 區塊標頭的形式加入 blob 金鑰。系統會保留其他表單欄位與區段,並傳送至上傳處理常式。如果您未指定內容類型,Blobstore 會嘗試從副檔名推論。如果系統無法判定內容類型,則會為新建的 blob 指派內容類型 application/octet-stream

提供 blob

如要提供 blob,您必須加上 blob 下載處理常式做為應用程式的路徑。這個處理常式應將目標 blob 的 blob 金鑰傳送至 blobstoreService.serve(blobKey, res);。在這個範例中,blob 金鑰會做為網址引數 (req.getParameter('blob-key')) 傳送至下載處理常式。實際上,下載處理常式可透過您選擇的任何方式來取得 blob 金鑰,例如透過其他方法或是使用者動作。

public void doGet(HttpServletRequest req, HttpServletResponse res)
    throws IOException {
        BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
        blobstoreService.serve(blobKey, res);

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),即便範圍重複也一樣。

完整的應用程式範例

在下列應用程式範例中,應用程式的主要網址會載入可用來向使用者要求上傳檔案的表單,接著上傳處理常式會立即呼叫下載處理常式來提供資料。此做法是為了簡化範例應用程式的內容。就實務而言,您大概不會使用主要網址來要求上傳資料,也不會立即提供剛剛才上傳的 blob。

// file Upload.java

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;

public class Upload extends HttpServlet {
    private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException {

        Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
        List<BlobKey> blobKeys = blobs.get("myFile");

        if (blobKeys == null || blobKeys.isEmpty()) {
            res.sendRedirect("/");
        } else {
            res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
        }
    }
}

// file Serve.java

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;

public class Serve extends HttpServlet {
    private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws IOException {
            BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
            blobstoreService.serve(blobKey, res);
        }
}

// file index.jsp

<%@ page import="com.google.appengine.api.blobstore.BlobstoreServiceFactory" %>
<%@ page import="com.google.appengine.api.blobstore.BlobstoreService" %>

<%
    BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
%>

<html>
    <head>
        <title>Upload Test</title>
    </head>
    <body>
        <form action="<%= blobstoreService.createUploadUrl("/upload") %>" method="post" enctype="multipart/form-data">
            <input type="text" name="foo">
            <input type="file" name="myFile">
            <input type="submit" value="Submit">
        </form>
    </body>
</html>

// web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

  <servlet>
    <servlet-name>Upload</servlet-name>
    <servlet-class>Upload</servlet-class>
  </servlet>

  <servlet>
    <servlet-name>Serve</servlet-name>
    <servlet-class>Serve</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Upload</servlet-name>
    <url-pattern>/upload</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>Serve</servlet-name>
    <url-pattern>/serve</url-pattern>
  </servlet-mapping>

</web-app>

使用圖片服務與 Blobstore

圖片服務可將 Blobstore 值做為轉換的來源。來源圖片的大小可達 Blobstore 值的上限大小。圖片服務仍會將轉換後的圖片傳回應用程式,因此轉換後的圖片必須小於 32 MB。這很適合用於建立由使用者上傳的大型相片縮圖。

如要瞭解如何將圖片服務與 Blobstore 值搭配使用,請參閱圖片服務說明文件

使用 Blobstore API 與 Google Cloud Storage

您可以使用 Blobstore API,將 blob 儲存至 Cloud Storage,而非儲存在 Blobstore。您必須按照 Google Cloud Storage 說明文件中所述的程序設定值區,然後在 BlobstoreService createUploadUrl 中指定值區和檔案名稱,並在 UploadOptions 參數中指定值區名稱。在上傳處理常式中,您需要處理傳回的 FileInfo 中繼資料,並明確儲存 Google Cloud Storage 檔案名稱以便稍後擷取 blob。

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

以下這段程式碼示範了具體的執行方式。這個範例採用的要求處理常式會在要求中取得值區名稱和物件名稱,利用所提供的值區和物件名稱建立 Blobstore 服務,並使用這項此服務建立 Google Cloud Storage 的 blob 金鑰。

BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
BlobKey blobKey = blobstoreService.createGsBlobKey(
    "/gs/" + fileName.getBucketName() + "/" + fileName.getObjectName());
blobstoreService.serve(blobKey, resp);

配額與限制

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

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

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

  • 應用程式透過單一 API 呼叫可讀取的 Blobstore 資料量上限為 32 MB。
  • 單一表單 POST 可上傳的檔案數量上限為 500 個。
本頁內容對您是否有任何幫助?請提供意見:

傳送您對下列選項的寶貴意見...

這個網頁
Java 適用的 App Engine 標準環境