

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 教學課程：使用 Amazon S3 觸發條件建立縮圖影像
<a name="with-s3-tutorial"></a>

在本教學課程中，您將建立和設定 Lambda 函數，它會調整新增至 Amazon Simple Storage Service (Amazon S3) 儲存貯體的映像。當您將映像檔案新增至儲存貯體時，Amazon S3 會調用 Lambda 函數。然後，函數會建立映像的縮圖版本，並將其輸出到不同 Amazon S3 儲存貯體。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_resources.png)


請執行下列步驟以完成本教學課程：

1. 建立來源和目的地 Amazon S3 儲存貯體，並上傳範例映像。

1. 建立可調整映像大小並將縮圖輸出到 Amazon S3 儲存貯體的 Lambda 函數。

1. 設定一個 Lambda 觸發條件，在物件上傳至來源儲存貯體時調用函數。

1. 首先使用虛擬事件測試函數，然後透過將映像上傳到來源儲存貯體來測試函數。

完成這些步驟後，將了解如何使用 Lambda 在新增至 Amazon S3 儲存貯體的物件上執行檔案處理任務。您可以使用 AWS Command Line Interface (AWS CLI) 或 來完成本教學課程 AWS 管理主控台。

如果您正在尋找更簡單的範例來學習如何為 Lambda 設定 Amazon S3 觸發條件，則可以嘗試[教學課程：使用 Amazon S3 觸發條件調用 Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html)。

**Topics**
+ [先決條件](#with-s3-example-prereqs)
+ [建立兩個 Amazon S3 儲存貯體](#with-s3-tutorial-prepare-create-buckets)
+ [將測試映像上傳到來源儲存貯體](#with-s3-tutorial-test-image)
+ [建立許可政策](#with-s3-tutorial-create-policy)
+ [建立執行角色](#with-s3-tutorial-create-execution-role)
+ [建立函數部署套件](#with-s3-tutorial-create-function-package)
+ [建立 Lambda 函式](#with-s3-tutorial-create-function-createfunction)
+ [設定 Amazon S3 以調用函數](#with-s3-tutorial-configure-s3-trigger)
+ [使用虛擬事件來測試 Lambda 函數](#with-s3-tutorial-dummy-test)
+ [使用 Amazon S3 觸發條件測試函數](#with-s3-tutorial-test-s3)
+ [清除您的資源](#s3-tutorial-cleanup)

## 先決條件
<a name="with-s3-example-prereqs"></a>

如果您想要使用 AWS CLI 來完成教學課程，請安裝[最新版本的 AWS Command Line Interface]()。

對於 Lambda 函數程式碼，您可以使用 Python 或 Node.js。為您想要使用的語言安裝語言支援工具和套件管理工具。

### 安裝 AWS Command Line Interface
<a name="install_aws_cli"></a>

如果您尚未安裝 AWS Command Line Interface，請依照[安裝或更新最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)中的步驟進行安裝。

本教學課程需使用命令列終端機或 Shell 來執行命令。在 Linux 和 macOS 中，使用您偏好的 Shell 和套件管理工具。

**注意**  
在 Windows 中，作業系統的內建終端不支援您常與 Lambda 搭配使用的某些 Bash CLI 命令 (例如 `zip`)。若要取得 Ubuntu 和 Bash 的 Windows 整合版本，請[安裝適用於 Linux 的 Windows 子系統](https://docs.microsoft.com/en-us/windows/wsl/install-win10)。

## 建立兩個 Amazon S3 儲存貯體
<a name="with-s3-tutorial-prepare-create-buckets"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps1.png)


首先建立兩個 Amazon S3 儲存貯體。第一個儲存貯體是將接收映像上傳的來源儲存貯體。當您調用函數時，Lambda 會使用第二個儲存貯體來儲存已調整大小的縮圖。

------
#### [ AWS 管理主控台 ]

**建立 Amazon S3 儲存貯體 (主控台)**

1. 開啟 [Amazon S3 主控台](https://console.aws.amazon.com/s3)，然後選取**一般用途儲存貯體**頁面。

1. 選取最 AWS 區域 接近您地理位置的 。可使用螢幕頂端的下拉式清單來變更區域。在本教學課程稍後的階段，您必須在同一區域中建立 Lambda 函數。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/console_region_select.png)

1. 選擇**建立儲存貯體**。

1. 在 **General configuration (一般組態)** 下，執行下列動作：

   1. 在**儲存貯體類型**欄位中，選取**一般用途**。

   1. 在**儲存貯體名稱**欄位中，輸入符合 Amazon S3 [儲存貯體命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)的全域唯一名稱。儲存貯體名稱只能包含小寫字母、數字、句點 (.) 和連字號 (-)。

1. 其他所有選項維持設為預設值，然後選擇**建立儲存貯體**。

1. 重複步驟 1 到 5 來建立目的地儲存貯體。對於**儲存貯體名稱**，輸入 `amzn-s3-demo-source-bucket-resized`，其中 `amzn-s3-demo-source-bucket` 是您剛才建立的來源儲存貯體名稱。

------
#### [ AWS CLI ]

**建立 Amazon S3 儲存貯體 (AWS CLI)**

1. 執行下列 CLI 命令以建立來源儲存貯體。您為儲存貯體選擇的名稱必須是全域唯一的，並遵循 Amazon S3 [儲存貯體命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)。名稱只能包含小寫字母、數字、句點 (.) 和連字號 (-)。對於 `region` 和 `LocationConstraint`，請選擇最接近您地理位置的 [AWS 區域](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html)。

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-source-bucket --region us-east-1 \
   --create-bucket-configuration LocationConstraint=us-east-1
   ```

   稍後在教學課程中，您必須在與來源儲存貯體 AWS 區域 相同的 中建立 Lambda 函數，因此請記下您選擇的區域。

1. 執行下列命令以建立目的地儲存貯體。對於儲存貯體名稱，必須使用 `amzn-s3-demo-source-bucket-resized`，其中 `amzn-s3-demo-source-bucket` 是您在步驟 1 中建立的來源儲存貯體名稱。針對 `region`和 `LocationConstraint`，選擇 AWS 區域 您用來建立來源儲存貯體的相同 。

   ```
   aws s3api create-bucket --bucket amzn-s3-demo-source-bucket-resized --region us-east-1 \
   --create-bucket-configuration LocationConstraint=us-east-1
   ```

------

## 將測試映像上傳到來源儲存貯體
<a name="with-s3-tutorial-test-image"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps2.png)


稍後在教學課程中，您將使用 AWS CLI 或 Lambda 主控台叫用 Lambda 函數來測試 Lambda 函數。若要確認函数運作正常，來源儲存貯體需要包含測試映像。此映像可以是您選擇的任何 JPG 或 PNG 檔案。

------
#### [ AWS 管理主控台 ]

**將測試映像上傳到來源儲存貯體 (主控台)**

1. 開啟 Amazon S3 主控台的[儲存貯體](https://console.aws.amazon.com/s3/buckets)頁面。

1. 選取您在上一個步驟所建立的來源儲存貯體。

1. 選擇**上傳**。

1. 選擇**新增檔案**，然後使用檔案選擇器選擇您要上傳的物件。

1. 選擇**開啟**，然後選擇**上傳**。

------
#### [ AWS CLI ]

**將測試映像上傳到來源儲存貯體 (AWS CLI)**
+ 從包含要上傳之映像的目錄中，執行下列 CLI 命令。將 `--bucket` 參數取代為來源儲存貯體名稱。對於 `--key` 和 `--body` 參數，請使用測試映像的檔案名稱。

  ```
  aws s3api put-object --bucket amzn-s3-demo-source-bucket --key HappyFace.jpg --body ./HappyFace.jpg
  ```

------

## 建立許可政策
<a name="with-s3-tutorial-create-policy"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps3.png)


建立 Lambda 函數的第一個步驟是建立許可政策。此政策為您的函數提供存取其他 AWS 資源所需的許可。在本教學課程中，該政策為 Lambda 提供了 Amazon S3 儲存貯體的讀取和寫入許可，並允許其寫入到 Amazon CloudWatch Logs 日誌。

------
#### [ AWS 管理主控台 ]

**建立政策 (主控台)**

1. 開啟 AWS Identity and Access Management (IAM) 主控台[的政策](https://console.aws.amazon.com/iamv2/home#policies)頁面。

1. 選擇**建立政策**。

1. 選擇 **JSON** 索引標籤，然後將下列政策貼到 JSON 編輯器。  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:PutLogEvents",
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream"
               ],
               "Resource": "arn:aws:logs:*:*:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:PutObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           }
       ]
   }
   ```

1. 選擇**下一步**。

1. 在**政策詳細資訊**下，針對政策**政策名稱** ，輸入 `LambdaS3Policy`。

1. 選擇**建立政策**。

------
#### [ AWS CLI ]

**建立政策 (AWS CLI)**

1. 將下面的 JSON 儲存在名為 `policy.json` 的檔案中。  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:PutLogEvents",
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream"
               ],
               "Resource": "arn:aws:logs:*:*:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:GetObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "s3:PutObject"
               ],
               "Resource": "arn:aws:s3:::*/*"
           }
       ]
   }
   ```

1. 在儲存 JSON 政策文件的目錄中執行下列 CLI 命令。

   ```
   aws iam create-policy --policy-name LambdaS3Policy --policy-document file://policy.json
   ```

------

## 建立執行角色
<a name="with-s3-tutorial-create-execution-role"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps4.png)


執行角色是授予 Lambda 函數存取 AWS 服務 和資源許可的 IAM 角色。若要為函數提供 Amazon S3 儲存貯體的讀取和寫入存取權，請連接您在上個步驟建立的許可政策。

------
#### [ AWS 管理主控台 ]

**建立執行角色並連接許可政策 (主控台)**

1. 開啟 (IAM) 主控台的[角色](https://console.aws.amazon.com/iamv2/home#roles)頁面。

1. 選擇建**立角色**。

1. 對於**可信實體類型**，選取 **AWS 服務**，然後針對**使用案例**選取 **Lambda**。

1. 選擇**下一步**。

1. 執行下列動作，新增您在上個步驟中建立的許可政策：

   1. 在政策搜尋方塊中，輸入 `LambdaS3Policy`。

   1. 在搜尋結果中，選取 `LambdaS3Policy` 的核取方塊。

   1. 選擇**下一步**。

1. 在**角色詳細資訊**下，針對**角色名稱**，輸入 `LambdaS3Role`。

1. 選擇建**立角色**。

------
#### [ AWS CLI ]

**建立執行角色並連接許可政策 (AWS CLI)**

1. 將下面的 JSON 儲存在名為 `trust-policy.json` 的檔案中。此信任政策允許 Lambda 透過授予服務主體呼叫 AWS Security Token Service (AWS STS) `AssumeRole`動作的許可來使用角色的`lambda.amazonaws.com`許可。  
****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "lambda.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

1. 在儲存 JSON 信任政策文件的目錄中，執行下列 CLI 命令，建立執行角色。

   ```
   aws iam create-role --role-name LambdaS3Role --assume-role-policy-document file://trust-policy.json
   ```

1. 執行下列 CLI 命令，連接您在上個步驟中建立的許可政策。將政策 ARN 中的 AWS 帳戶 號碼取代為您自己的帳戶號碼。

   ```
   aws iam attach-role-policy --role-name LambdaS3Role --policy-arn arn:aws:iam::123456789012:policy/LambdaS3Policy
   ```

------

## 建立函數部署套件
<a name="with-s3-tutorial-create-function-package"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps5.png)


要建立函數，需建立包含函數程式碼和其相依項的*部署套件*。對於此 `CreateThumbnail` 函數，函數程式碼使用單獨的程式庫來調整映像大小。依照所選語言的指示，建立包含所需程式庫的部署套件。

------
#### [ Node.js ]

**建立部署套件 (Node.js)**

1. 為函數程式碼和相依項建立名為 `lambda-s3` 的目錄並導覽到該目錄。

   ```
   mkdir lambda-s3
   cd lambda-s3
   ```

1. 使用 `npm` 建立新 Node.js 專案。若要接受互動體驗中提供的預設選項，請按下 `Enter`。

   ```
   npm init
   ```

1. 將以下函數程式碼儲存在名為 `index.mjs` 檔案中。請務必以您建立來源和目的地儲存貯體的 AWS 區域 取代 `us-east-1`。

   ```
   // dependencies
   import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
   
   import { Readable } from 'stream';
   
   import sharp from 'sharp';
   import util from 'util';
   
   
   // create S3 client
   const s3 = new S3Client({region: 'us-east-1'});
   
   // define the handler function
   export const handler = async (event, context) => {
   
   // Read options from the event parameter and get the source bucket
   console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
     const srcBucket = event.Records[0].s3.bucket.name;
     
   // Object key may have spaces or unicode non-ASCII characters
   const srcKey    = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
   const dstBucket = srcBucket + "-resized";
   const dstKey    = "resized-" + srcKey;
   
   // Infer the image type from the file suffix
   const typeMatch = srcKey.match(/\.([^.]*)$/);
   if (!typeMatch) {
     console.log("Could not determine the image type.");
     return;
   }
   
   // Check that the image type is supported
   const imageType = typeMatch[1].toLowerCase();
   if (imageType != "jpg" && imageType != "png") {
     console.log(`Unsupported image type: ${imageType}`);
     return;
   }
   
   // Get the image from the source bucket. GetObjectCommand returns a stream.
   try {
     const params = {
       Bucket: srcBucket,
       Key: srcKey
     };
     var response = await s3.send(new GetObjectCommand(params));
     var stream = response.Body;
     
   // Convert stream to buffer to pass to sharp resize function.
     if (stream instanceof Readable) {
       var content_buffer = Buffer.concat(await stream.toArray());
       
     } else {
       throw new Error('Unknown object stream type');
     }
   
   
   } catch (error) {
     console.log(error);
     return;
   }
   
     
   // set thumbnail width. Resize will set the height automatically to maintain aspect ratio.
   const width  = 200;
   
   // Use the sharp module to resize the image and save in a buffer.
   try {    
     var output_buffer = await sharp(content_buffer).resize(width).toBuffer();
   
   } catch (error) {
     console.log(error);
     return;
   }
   
   // Upload the thumbnail image to the destination bucket
   try {
     const destparams = {
       Bucket: dstBucket,
       Key: dstKey,
       Body: output_buffer,
       ContentType: "image"
     };
   
     const putResult = await s3.send(new PutObjectCommand(destparams));
   
     } catch (error) {
       console.log(error);
       return;
     }
   
     console.log('Successfully resized ' + srcBucket + '/' + srcKey +
       ' and uploaded to ' + dstBucket + '/' + dstKey);
     };
   ```

1. 在 `lambda-s3` 目錄中，使用 npm 安裝 Sharp 程式庫。請注意，最新的 Sharp 版本 (0.33) 與 Lambda 不相容。安裝版本 0.32.6 以完成本教學課程。

   ```
   npm install sharp@0.32.6
   ```

   npm `install` 命令為您的模組建立一個 `node_modules` 目錄。在此步驟之後，目錄結構應如下所示。

   ```
   lambda-s3
   |- index.mjs
   |- node_modules
   |  |- base64js
   |  |- bl
   |  |- buffer
   ...
   |- package-lock.json
   |- package.json
   ```

1. 建立包含函數程式碼及其相依項 .zip 部署套件。在 MacOS 或 Linux 中，執行下列命令。

   ```
   zip -r function.zip .
   ```

   在 Windows 中，使用您偏好的 zip 公用程式建立 .zip 檔案。請確保 `index.mjs`、`package.json` 和 `package-lock.json` 檔案以及 `node_modules` 目錄全部都位於 .zip 檔案的根目錄。

------
#### [ Python ]

**建立部署套件 (Python)**

1. 將程式碼範例儲存為名為 `lambda_function.py` 的檔案。

   ```
   import boto3
   import os
   import sys
   import uuid
   from urllib.parse import unquote_plus
   from PIL import Image
   import PIL.Image
               
   s3_client = boto3.client('s3')
               
   def resize_image(image_path, resized_path):
     with Image.open(image_path) as image:
       image.thumbnail(tuple(x / 2 for x in image.size))
       image.save(resized_path)
               
   def lambda_handler(event, context):
     for record in event['Records']:
       bucket = record['s3']['bucket']['name']
       key = unquote_plus(record['s3']['object']['key'])
       tmpkey = key.replace('/', '')
       download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
       upload_path = '/tmp/resized-{}'.format(tmpkey)
       s3_client.download_file(bucket, key, download_path)
       resize_image(download_path, upload_path)
       s3_client.upload_file(upload_path, '{}-resized'.format(bucket), 'resized-{}'.format(key))
   ```

1. 在建立 `lambda_function.py` 檔案的同一個目錄中，建立名為 `package` 的新目錄並安裝 [Pillow (PIL)](https://pypi.org/project/Pillow/) 程式庫和 適用於 Python (Boto3) 的 AWS SDK。雖然 Lambda Python 執行期包含 Boto3 SDK 的版本，但建議您將函數的所有相依項新增至部署套件，即使其包含在執行期中。如需詳細資訊，請參閱 [Python 中的執行期相依項](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-dependencies)。

   ```
   mkdir package
   pip install \
   --platform manylinux2014_x86_64 \
   --target=package \
   --implementation cp \
   --python-version 3.12 \
   --only-binary=:all: --upgrade \
   pillow boto3
   ```

   Pillow 程式庫中包含 C/C \$1\$1 程式碼。使用 `--platform manylinux_2014_x86_64` 和 `--only-binary=:all:` 選項，pip 便會下載並安裝適用的 Pillow 版本，其中包含與 Amazon Linux 2 作業系統相容的預先編譯二進位檔。這可確保無論本機建置機器的作業系統和架構為何，您的部署套件都能在 Lambda 執行環境中運作。

1. 建立一個包含應用程式碼以及 Pillow 和 Boto3 程式庫的 .zip 檔案。在 Linux 或 MacOS 中，使用命令列界面執行下列命令。

   ```
   cd package
   zip -r ../lambda_function.zip .
   cd ..
   zip lambda_function.zip lambda_function.py
   ```

    在 Windows 中，使用您偏好的 zip 工具建立 `lambda_function.zip` 檔案。確保包含相依項的 `lambda_function.py` 檔案和資料夾全部都在 .zip 檔案的根目錄中。

您也可以使用 Python 虛擬環境建立部署套件。請參閱 [使用 .zip 封存檔部署 Python Lambda 函數](python-package.md)

------

## 建立 Lambda 函式
<a name="with-s3-tutorial-create-function-createfunction"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps6.png)


您可以使用 AWS CLI 或 Lambda 主控台建立 Lambda 函數。依照所選語言的指示建立函數。

------
#### [ AWS 管理主控台 ]

**建立函數的方式 (主控台)**

要使用主控台建立 Lambda 函數，首先建立包含一些 ‘Hello world’ 程式碼的基本函數。然後，透過上傳您在上一個步驟中建立的 .zip 或 JAR 檔案，將此程式碼取代為您自己的函數程式碼。

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 請確定您使用 AWS 區域 與建立 Amazon S3 儲存貯體相同的 。可使用螢幕頂端的下拉式清單來變更區域。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/console_region_select.png)

1. 選擇 **Create function (建立函數)**。

1. 選擇 **Author from scratch** (從頭開始撰寫)。

1. 在**基本資訊**下，請執行下列動作：

   1. 針對**函數名稱**，請輸入 `CreateThumbnail`。

   1. 對於**執行時期**，請根據您為函數選擇的語言，選擇 **Node.js 22.x** 或 **Python 3.12**。

   1. 對於 **Architecture** (架構)，選擇 **x86\$164**。

1. 在**變更預設執行角色**索引標籤中，執行下列操作：

   1. 展開索引標籤，然後選擇**使用現有角色**。

   1. 選擇您之前建立的 `LambdaS3Role`。

1. 選擇**建立函數**。

**上傳函數程式碼 (主控台)**

1. 在**程式碼來源**窗格中選擇**上傳來源**。

1. 選擇 **.zip 檔案**。

1. 選擇**上傳**。

1. 在檔案選擇器中，選取 .zip 檔案，並選擇**開啟**。

1. 選擇**儲存**。

------
#### [ AWS CLI ]

**建立函數 (AWS CLI)**
+ 執行所選語言的 CLI 命令。針對 `role` 參數，請務必將 取代`123456789012`為您自己的 AWS 帳戶 ID。對於 `region` 參數，將 `us-east-1` 取代為您建立 Amazon S3 儲存貯體所在的區域。
  + 對於 **Node.js**，請從包含 `function.zip` 檔案的目錄中執行下列命令。

    ```
    aws lambda create-function --function-name CreateThumbnail \
    --zip-file fileb://function.zip --handler index.handler --runtime nodejs24.x \
    --timeout 10 --memory-size 1024 \
    --role arn:aws:iam::123456789012:role/LambdaS3Role --region us-east-1
    ```
  + 對於 **Python**，請從包含 `lambda_function.zip` 檔案的目錄中執行下列命令。

    ```
    aws lambda create-function --function-name CreateThumbnail \
    --zip-file fileb://lambda_function.zip --handler lambda_function.lambda_handler \
    --runtime python3.14 --timeout 10 --memory-size 1024 \
    --role arn:aws:iam::123456789012:role/LambdaS3Role --region us-east-1
    ```

------

## 設定 Amazon S3 以調用函數
<a name="with-s3-tutorial-configure-s3-trigger"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps7.png)


若要在將映像上傳至來源儲存貯體時執行 Lambda 函數，您需要設定函數的觸發條件。可以使用主控台或 AWS CLI來設定 Amazon S3 觸發條件。

**重要**  
此程序會將 Amazon S3 儲存貯體設定為每次在儲存貯體中建立物件時即會調用您的函數。請務必僅在來源儲存貯體上進行設定。如果 Lambda 函數在進行調用的同一個儲存貯體中建立物件，則可以[在一個迴圈中連續調用](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway)函數。這可能會導致未預期的費用向您的 收費 AWS 帳戶。

------
#### [ AWS 管理主控台 ]

**設定 Amazon S3 觸發條件 (主控台)**

1. 開啟 Lambda 主控台的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)，然後選擇您的函數 (`CreateThumbnail`)。

1. 選擇 **Add trigger (新增觸發條件)**。

1. 選取 **S3**。

1. 在**儲存貯體**下，選取您的來源儲存貯體。

1. 在**事件類型**下，選取**所有物件建立事件**。

1. 在**遞迴調用**下，選取核取方塊，確認您了解不建議使用相同的 Amazon S3 儲存貯體進行輸入和輸出作業。您可以閱讀無伺服器園地中 [導致 Lambda 函數失控的遞迴模式](https://serverlessland.com/content/service/lambda/guides/aws-lambda-operator-guide/recursive-runaway)，進一步了解 Lambda 中的遞迴調用模式。

1. 選擇**新增**。

   當您使用 Lambda 主控台建立觸發條件時，Lambda 會自動建立[資源型政策](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)，為您選取的服務授予調用函數的許可。

------
#### [ AWS CLI ]

**設定 Amazon S3 觸發條件 (AWS CLI)**

1. 若要讓 Amazon S3 來源儲存貯體在新增映像檔案時調用函數，您首先需要使用[資源型政策](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)為函數設定許可。資源型政策陳述式提供叫用 函數的其他 AWS 服務 許可。若要授予 Amazon S3 調用函數的許可，請執行下列 CLI 命令。請務必以您自己的 AWS 帳戶 ID 取代 `source-account` 參數，並使用您自己的來源儲存貯體名稱。

   ```
   aws lambda add-permission --function-name CreateThumbnail \
   --principal s3.amazonaws.com --statement-id s3invoke --action "lambda:InvokeFunction" \
   --source-arn arn:aws:s3:::amzn-s3-demo-source-bucket \
   --source-account 123456789012
   ```

   使用此命令定義的政策允許 Amazon S3 僅在來源儲存貯體上發生動作時調用函數。
**注意**  
雖然 Amazon S3 儲存貯體名稱全域唯一，但是在使用資源型政策時，最佳實務是指定儲存貯體必須屬於您的帳戶。這是因為如果您刪除儲存貯體，另一個 可以使用相同的 Amazon Resource Name (ARN) AWS 帳戶 建立儲存貯體。

1. 將下面的 JSON 儲存在名為 `notification.json` 的檔案中。套用至來源儲存貯體時，此 JSON 會設定儲存貯體，以便在每次新增新物件時傳送通知至 Lambda 函數。將 AWS 帳戶 Lambda 函數 ARN AWS 區域 中的數字 和 取代為您自己的帳號和區域。

   ```
   {
   "LambdaFunctionConfigurations": [
       {
         "Id": "CreateThumbnailEventConfiguration",
         "LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:CreateThumbnail",
         "Events": [ "s3:ObjectCreated:Put" ]
       }
     ]
   }
   ```

1. 執行下列 CLI 命令，將您建立的 JSON 檔案中的通知設定套用至來源儲存貯體。用您自己的來源儲存貯體名稱取代 `amzn-s3-demo-source-bucket`。

   ```
   aws s3api put-bucket-notification-configuration --bucket amzn-s3-demo-source-bucket \
   --notification-configuration file://notification.json
   ```

   若要深入了解 `put-bucket-notification-configuration` 命令和 `notification-configuration` 選項，請參閱 *AWS CLI 命令參考*中的 [put-bucket-notification-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-notification-configuration.html)。

------

## 使用虛擬事件來測試 Lambda 函數
<a name="with-s3-tutorial-dummy-test"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps8.png)


在將映像檔案新增至 Amazon S3 來源儲存貯體以測試整個設定之前，可以透過使用虛擬事件調用 Lambda 函數來測試其是否正常運作。Lambda 中的事件是一種 JSON 格式的文件，它包含供函數處理的資料。Amazon S3 調用函數時，傳送至函數的事件會包含諸如儲存貯體名稱、儲存貯體 ARN 和物件金鑰等資訊。

------
#### [ AWS 管理主控台 ]

**使用虛擬事件來測試 Lambda 函數 (主控台)**

1. 開啟 Lambda 主控台的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)，然後選擇您的函數 (`CreateThumbnail`)。

1. 選擇**測試**標籤。

1. 若要建立測試事件，請在**測試事件**窗格中執行下列動作：

   1. 在**測試事件動作**下方，選取**建立新事件**。

   1. **事件名稱**輸入 **myTestEvent**。

   1. 對於**範本**，選取 **S3 Put**。

   1. 將下列參數的值取代為您自己的值。
      + 對於 `awsRegion`，`us-east-1`將 取代 AWS 區域 為您在其中建立 Amazon S3 儲存貯體的 。
      + 對於 `name`，將 `amzn-s3-demo-bucket` 取代為 Amazon S3 來源儲存貯體的名稱。
      + 對於 `key`，將 `test%2Fkey` 取代為您在步驟 [將測試映像上傳到來源儲存貯體](#with-s3-tutorial-test-image) 中上傳至來源儲存貯體之測試物件的檔案名稱。

      ```
      {
        "Records": [
          {
            "eventVersion": "2.0",
            "eventSource": "aws:s3",
            "awsRegion": "us-east-1",
            "eventTime": "1970-01-01T00:00:00.000Z",
            "eventName": "ObjectCreated:Put",
            "userIdentity": {
              "principalId": "EXAMPLE"
            },
            "requestParameters": {
              "sourceIPAddress": "127.0.0.1"
            },
            "responseElements": {
              "x-amz-request-id": "EXAMPLE123456789",
              "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
            },
            "s3": {
              "s3SchemaVersion": "1.0",
              "configurationId": "testConfigRule",
              "bucket": {
                "name": "amzn-s3-demo-bucket",
                "ownerIdentity": {
                  "principalId": "EXAMPLE"
                },
                "arn": "arn:aws:s3:::amzn-s3-demo-bucket"
              },
              "object": {
                "key": "test%2Fkey",
                "size": 1024,
                "eTag": "0123456789abcdef0123456789abcdef",
                "sequencer": "0A1B2C3D4E5F678901"
              }
            }
          }
        ]
      }
      ```

   1. 選擇**儲存**。

1. 在**測試事件**窗格中，選擇**測試**。

1. 若要檢查您的函數已建立大小經過調整的映像版本並將其存放在目標 Amazon S3 儲存貯體中，請執行以下操作：

   1. 開啟 Amazon S3 主控台的[儲存貯體](https://console.aws.amazon.com/s3/buckets)頁面。

   1. 選擇目標儲存貯體，並確認在**物件**窗格中列出已調整大小的檔案。

------
#### [ AWS CLI ]

**使用虛擬事件來測試 Lambda 函數 (AWS CLI)**

1. 將下面的 JSON 儲存在名為 `dummyS3Event.json` 的檔案中。將下列參數的值取代為您自己的值：
   + 對於 `awsRegion`，`us-east-1`將 取代 AWS 區域 為您在其中建立 Amazon S3 儲存貯體的 。
   + 對於 `name`，將 `amzn-s3-demo-bucket` 取代為 Amazon S3 來源儲存貯體的名稱。
   + 對於 `key`，將 `test%2Fkey` 取代為您在步驟 [將測試映像上傳到來源儲存貯體](#with-s3-tutorial-test-image) 中上傳至來源儲存貯體之測試物件的檔案名稱。

   ```
   {
     "Records": [
       {
         "eventVersion": "2.0",
         "eventSource": "aws:s3",
         "awsRegion": "us-east-1",
         "eventTime": "1970-01-01T00:00:00.000Z",
         "eventName": "ObjectCreated:Put",
         "userIdentity": {
           "principalId": "EXAMPLE"
         },
         "requestParameters": {
           "sourceIPAddress": "127.0.0.1"
         },
         "responseElements": {
           "x-amz-request-id": "EXAMPLE123456789",
           "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
         },
         "s3": {
           "s3SchemaVersion": "1.0",
           "configurationId": "testConfigRule",
           "bucket": {
             "name": "amzn-s3-demo-bucket",
             "ownerIdentity": {
               "principalId": "EXAMPLE"
             },
             "arn": "arn:aws:s3:::amzn-s3-demo-bucket"
           },
           "object": {
             "key": "test%2Fkey",
             "size": 1024,
             "eTag": "0123456789abcdef0123456789abcdef",
             "sequencer": "0A1B2C3D4E5F678901"
           }
         }
       }
     ]
   }
   ```

1. 在您儲存 `dummyS3Event.json` 檔案的目錄中，透過執行下列 CLI 命令來調用函數。此命令透過將 `RequestResponse` 指定為調用類型參數的值來同步調用 Lambda 函數。若要進一步了解同步和非同步調用，請參閱[調用 Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html)。

   ```
   aws lambda invoke --function-name CreateThumbnail \
   --invocation-type RequestResponse --cli-binary-format raw-in-base64-out \
   --payload file://dummyS3Event.json outputfile.txt
   ```

   如果使用的是 AWS CLI 版本 2，則需要 cli-binary-format 選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。如需詳細資訊，請參閱《[支援AWS CLI 的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)》。

1. 確認函數已建立映像的縮圖版本，並將其儲存到目標 Amazon S3 儲存貯體。執行以下 CLI 命令，將 `amzn-s3-demo-source-bucket-resized` 取代為您自己的目的地儲存貯體的名稱。

   ```
   aws s3api list-objects-v2 --bucket amzn-s3-demo-source-bucket-resized
   ```

   您應該會看到類似下列的輸出。`Key` 參數會顯示調整大小後的映像檔案名稱。

   ```
   {
       "Contents": [
           {
               "Key": "resized-HappyFace.jpg",
               "LastModified": "2023-06-06T21:40:07+00:00",
               "ETag": "\"d8ca652ffe83ba6b721ffc20d9d7174a\"",
               "Size": 2633,
               "StorageClass": "STANDARD"
           }
       ]
   }
   ```

------

## 使用 Amazon S3 觸發條件測試函數
<a name="with-s3-tutorial-test-s3"></a>

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/services-s3-tutorial/s3thumb_tut_steps9.png)


既然您已確認 Lambda 函數運作正常，便可將映像檔案新增至 Amazon S3 來源儲存貯體來測試完整的設定。將映像新增至來源儲存貯體時，應該會自動調用 Lambda 函數。函數會建立已調整大小的檔案版本，並將其存放在目標儲存貯體中。

------
#### [ AWS 管理主控台 ]

**使用 Amazon S3 觸發條件測試 Lambda 函數 (主控台)**

1. 若要將映像上傳到 Amazon S3 儲存貯體，請執行以下操作：

   1. 開啟 Amazon S3 主控台的[儲存貯體](https://console.aws.amazon.com/s3/buckets)頁面，並選擇來源儲存貯體。

   1. 選擇**上傳**。

   1. 選擇**新增檔案**，然後使用檔案選擇器選擇您要上傳的映像檔案。映像物件可以是任何 .jpg 或 .png 檔案。

   1. 選擇**開啟**，然後選擇**上傳**。

1. 透過執行下列操作，確認 Lambda 已在目標儲存貯體中儲存了調整大小後的映像檔案版本：

   1. 導覽回 Amazon S3 主控台的[儲存貯體](https://console.aws.amazon.com/s3/buckets)頁面，然後選擇目的地儲存貯體。

   1. 在**物件**窗格中，現在應該會看到兩個已調整大小的映像檔案，分別來自 Lambda 函數的每個測試。若要下載已調整大小的映像，請選取檔案，然後選擇**下載**。

------
#### [ AWS CLI ]

**使用 Amazon S3 觸發條件測試 Lambda 函數 (AWS CLI)**

1. 從包含要上傳之映像的目錄中，執行下列 CLI 命令。將 `--bucket` 參數取代為來源儲存貯體名稱。對於 `--key` 和 `--body` 參數，請使用測試映像的檔案名稱。測試映像可以是任何 .jpg 或 .png 檔案。

   ```
   aws s3api put-object --bucket amzn-s3-demo-source-bucket --key SmileyFace.jpg --body ./SmileyFace.jpg
   ```

1. 確認函數已建立映像的縮圖版本，並將其儲存到目標 Amazon S3 儲存貯體。執行以下 CLI 命令，將 `amzn-s3-demo-source-bucket-resized` 取代為您自己的目的地儲存貯體的名稱。

   ```
   aws s3api list-objects-v2 --bucket amzn-s3-demo-source-bucket-resized
   ```

   如果函數成功運作，則您會看到類似以下內容的輸出。您的目標儲存貯體現在應包含兩個已調整大小的檔案。

   ```
   {
       "Contents": [
           {
               "Key": "resized-HappyFace.jpg",
               "LastModified": "2023-06-07T00:15:50+00:00",
               "ETag": "\"7781a43e765a8301713f533d70968a1e\"",
               "Size": 2763,
               "StorageClass": "STANDARD"
           },
           {
               "Key": "resized-SmileyFace.jpg",
               "LastModified": "2023-06-07T00:13:18+00:00",
               "ETag": "\"ca536e5a1b9e32b22cd549e18792cdbc\"",
               "Size": 1245,
               "StorageClass": "STANDARD"
           }
       ]
   }
   ```

------

## 清除您的資源
<a name="s3-tutorial-cleanup"></a>

除非您想要保留為此教學課程建立的資源，否則您現在便可刪除。透過刪除您不再使用 AWS 的資源，您可以避免不必要的 費用 AWS 帳戶。

**若要刪除 Lambda 函數**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您建立的函數。

1. 選擇 **Actions** (動作)、**Delete** (刪除)。

1. 在文字輸入欄位中輸入 **confirm**，然後選擇 **Delete** (刪除)。

**刪除您建立的政策**

1. 開啟 IAM 主控台中的 [Policies (政策) 頁面](https://console.aws.amazon.com/iam/home#/policies)。

1. 選取您建立的政策 (**AWSLambdaS3Policy**)。

1. 選擇**政策動作**，然後**刪除**。

1. 選擇 **刪除** 。

**若要刪除執行角色**

1. 開啟 IAM 主控台中的 [角色頁面](https://console.aws.amazon.com/iam/home#/roles) 。

1. 選取您建立的執行角色。

1. 選擇**刪除**。

1. 在文字輸入欄位中輸入角色的名稱，然後選擇**刪除**。

**刪除 S3 儲存貯體**

1. 開啟 [Amazon S3 主控台](https://console.aws.amazon.com//s3/home#)。

1. 選擇您建立的儲存貯體。

1. 選擇 **刪除** 。

1. 在文字輸入欄位中輸入儲存貯體的名稱。

1. 選擇**刪除儲存貯體**。