瞭解如何使用工作佇列及 App Engine Image API 調整圖片大小。
工作佇列可以在直接的使用者互動之外執行程式碼,允許工作在背景中執行。本指南說明如何使用工作佇列,在將圖片新增至 Cloud Storage 之後執行工作。下列為工作佇列中所要執行的工作:
- 擷取剛才上傳至 Cloud Storage 的圖片。
- 使用 Image API 將圖片大小調整為縮圖圖片。
- 將完成的圖片儲存至 Cloud Storage。
App Engine Java 8 執行階段也支援使用 Java 的原生圖片操縱類別,例如 AWT 和 Java2D。
事前準備
本指南使用 Apache Commons IOUtils 程式庫。若要將 IOUtils 程式庫加入您的 App Engine 專案:
新增至
pom.xml
:<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
匯入程式庫
本指南提供的範例程式碼使用下列匯入功能:
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;
import org.apache.commons.io.IOUtils;
建立工作佇列
雖然 App Engine 提供 default
工作佇列,但您可以為不同類型的工作建立不同的工作佇列。舉例來說,您可以建立一個工作佇列來調整圖片大小,另一個則用於更新應用程式資料庫。
如要新增佇列,請在 App Engine 專案的 WEB-INF
目錄中建立 queue.xml
檔案。工作佇列必須指定名稱和執行速率:
<?xml version="1.0" encoding="UTF-8"?>
<queue-entries>
<queue>
<name>resize-image</name>
<rate>60/h</rate>
</queue>
</queue-entries>
這個範例佇列名為 resize-image
,定義執行速率為每小時 60 次或每分鐘 1 次。如要查看完整的清單佇列選項,請參閱 queue.xml
參考資料。
工作佇列有兩個元件:工作要求者和工作處理常式。要求者可以將工作新增至佇列,並傳送工作給工作處理常式。
將工作新增至佇列
如要將工作加入佇列:
使用
QueueFactory.getQueue()
建立工作佇列物件,確認您指定了queue.xml
中所定義的佇列名稱:Queue imageResizeQueue; // Taskqueue queue @Override public void init() throws ServletException { // Setup Cloud Storage service gcsService = GcsServiceFactory.createGcsService( new RetryParams.Builder() .initialRetryDelayMillis(10) .retryMaxAttempts(10) .totalRetryPeriodMillis(15000) .build()); // Initialize the queue object with the specific queue imageResizeQueue = QueueFactory.getQueue([QUEUE-NAME]); // Cloud SQL connection setup try { final String url = System.getProperty("cloudsql"); // Cloud SQL server URI try { conn = DriverManager.getConnection(url); // Connect to the database Statement createTable; // SQL statement // Batch SQL table creation commands createTable.addBatch(createContentTableSql); createTable.addBatch(createUserTableSql); createTable.addBatch(createImageTableSql); createTable.addBatch(createBlogPostImageTableSql); conn.createTable.executeBatch(); // Execute batch } catch (SQLException e) { throw new ServletException("Unable to connect to Cloud SQL", e); } } finally { // Nothing really to do here. } }
將工作新增至
Queue
物件。如同程式碼範例所示,imageResizeQueue.add()
會將工作新增至imageResizeQueue
物件:try { // Add a queued task to create a thumbnail of the uploaded image imageResizeQueue.add( TaskOptions.Builder.withUrl("/tasks/imageresize").param("filename", filename)); }
使用
TaskOptions.Builder.withUrl()
以及任何傳送至處理常式的參數,以指定工作處理常式的 URI。在此範例中,URI 為
/tasks/imageresize
,參數則是名稱為filename
的變數,其中包含待處理圖片的檔案名稱。
建立工作處理常式
將工作加入佇列之後,對應到 URI /tasks/imageresize
的工作處理常式便會執行。工作處理常式為 Java Servlet,其會嘗試執行工作直到成功為止。
在本範例中,工作處理常式會執行三項工作:
從 Cloud Storage 中擷取呼叫者指定的圖片。
使用 App Engine Image API 轉換圖片,在本範例中為縮圖圖片。
將已完成轉換的圖片 (縮圖) 儲存至 Cloud Storage。
如要建立工作處理常式:
新增可將處理常式對應至 URI
/tasks/imageresize
的註解:@WebServlet(name = "imageResize", description = "Task queue handler", urlPatterns = "/tasks/imageresize") public class imageResize extends HttpServlet { // Task handler functionality }
依照 Cloud Storage 使用指南的說明,設定連線至 Cloud Storage,並從 Cloud Storage 中擷取圖片:
public void init() throws ServletException { // initiate GcsService GcsService gcsService = GcsServiceFactory.createGcsService( new RetryParams.Builder() .initialRetryDelayMillis(10) .retryMaxAttempts(10) .totalRetryPeriodMillis(15000) .build()); }
處理傳入的工作佇列要求,使用提供的檔案名稱從 Cloud Storage 內擷取圖片:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String filename = req.getParameter("filename"); // Get the filename passed from the task requestor GcsFilename gcsFile = new GcsFilename(bucket, filename); // Create a valid Cloud Storage filename GcsInputChannel readChannel = gcsService.openPrefetchingReadChannel(gcsFile, 0, BUFFER_SIZE); // Read the file from Cloud Storage
使用
ImagesService
物件調整圖片大小:// Get an instance of the ImagesService we can use to transform images. ImagesService imagesService = ImagesServiceFactory.getImagesService(); // Make an image directly from a byte array, and transform it. Image image = ImagesServiceFactory.makeImage(IOUtils.toByteArray(Channels.newInputStream(readChannel))); Transform resize = ImagesServiceFactory.makeResize(100, 50); // resize image to 100x50 Image resizedImage = imagesService.applyTransform(resize, image); // Write the transformed image back to a Cloud Storage object. gcsService.createOrReplace( new GcsFilename(bucket, "thumbnail_" + filename), new GcsFileOptions.Builder().acl("public-read").build(), ByteBuffer.wrap(resizedImage.getImageData()));
上方程式碼片段採用 Image API
makeResize()
方法將圖片的大小調整為縮圖。為此,程式碼片段會將 Cloud Storage 內的圖片讀入InputChannel
,然後透過IOUtils.toByteArray()
將圖片轉換成 ByteArray。套用轉換之後,新圖片的檔案名稱會附加上字串
thumbnail_
,且權限設定為可公開讀取,並寫入 Cloud Storage。
保護工作處理常式網址
您應該保護執行機密作業的工作 (例如資料修改),以便讓外部使用者無法直接呼叫該工作。如要執行保護措施,您可以設定僅限 App Engine 管理員存取工作,這樣能防止使用者存取工作網址。請注意,這項限制不會套用至來自 App Engine 應用程式的工作要求。
在目前的範例中,工作處理常式在 /tasks/
資料夾中擁有網址。如要設定僅限 App Engine 管理員存取 /tasks/
資料夾,請將以下內容新增到專案的 web.xml
中。
<security-constraint>
<web-resource-collection>
<web-resource-name>tasks</web-resource-name>
<url-pattern>/tasks/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
移除佇列中的單項工作
如要從佇列中移除單項工作,請使用 deleteTask()
:
private void removeTask(Queue queue, String taskName) {
queue.deleteTask(taskName); // remove a task from a queue
}
移除佇列中的所有工作
如要從佇列中移除所有工作,請使用 purge()
。清除作業可能需要一分鐘才能移除佇列中的所有工作。
private void purgeQueue(Queue queue) {
queue.purge(); // remove all tasks from a queue
}
由於從佇列中刪除所有工作可能需要一分鐘的時間,因此您應該先等候幾秒鐘,然後再將新工作新增到佇列。
刪除工作佇列
如要刪除工作佇列,請從專案的 queue.xml
檔案中移除項目,然後重新部署。
部署至 App Engine
您可以透過 Maven 將應用程式部署至 App Engine。
請前往專案的根目錄,並輸入以下內容:
mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID
將 PROJECT_ID 替換為您的 Google Cloud 專案 ID。如果 pom.xml
檔案已指定專案 ID,您就不需要在執行的指令中加入 -Dapp.deploy.projectId
屬性。
請在 Maven 部署應用程式後輸入下列指令,以便在新的應用程式中自動開啟網路瀏覽器分頁:
gcloud app browse
後續步驟
本指南說明如何透過工作佇列建立圖片縮圖,並將其儲存至 Cloud Storage。工作佇列也可以與 Cloud Datastore 或 Cloud SQL 等其他儲存空間服務搭配使用。