iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Python

在AWS上進行物聯網與人工智慧實作系列 第 26

D26-實驗:使用 POST 方法上傳圖片 - Lambda

  • 分享至 

  • xImage
  •  

實驗:使用 POST 方法上傳圖片 - Lambda

目錄

使用 S3 來儲存照片可以很容易的建立一個無服務器的應用,只要結合 API Gateway 與 AWS Lambda 就可以讓使用者在不需建置任何服務器的情況下,提供一個照片存放的功能,本實驗將提供這樣的整合練習:API Gateway+Lambda+S3

啟動學習者實驗室

AWS Academy Learner Lab 是提供一個帳號讓學生可以自行使用 AWS 的服務,讓學生可以在 50 USD的金額下,自行練習所要使用的 AWS 服務,在此先介紹一下 Learner Lab 基本操作與限制。
AWS Academy 學習平台 的入口首頁 https://www.awsacademy.com/LMS_Login ,選擇以學生 (Students) 身分登錄,在課程選單中選擇 AWS Academy Learner Lab - Foundation Services 的課程,在課程選單中選擇 單元 (Module),接著單擊 啟動 AWS Academy Learner Lab,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510ZKUlCId9zU.png
圖 1. 啟動 AWS Academy Learner Lab

進入 Learner Lab 中,說明一下每個區塊,圖形在下方。

  1. 用來啓動 AWS 管理控制台介面,必須是出現綠點才可以點擊,而出現綠點必須要先啓動實驗 (Start Lab)
  2. 已用金額與全部實驗金額 (Used $0.2 of $50)。
  3. 工具列說明:
    • 『Start Lab』:開始實驗帳號,這時候就可以使用 AWS 資源。
    • 『End Lab』:就會停止計費,並把所有的 AWS 資源關閉,注意,這只是暫停這些資源,並不會回收。
    • 『AWS Details』:使用者(IAM 用戶)相關的密鑰資料可以從來取得。
    • 『Readme』:說明手冊,就是下方的 5.
    • 『Reset』:就會把目前所有的 AWS 設定好的資源都清除掉。
  4. 切換說明的語系,ZH-CN 是簡體中文。
  5. 說明手冊。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510A2TxvuuQbe.png
圖 2. Learner Lab 畫面說明

建立 S3 儲存貯體

連接到 AWS Cloud9 IDE 並配置環境

AWS Cloud9 IDE 畫面與 VS Code 畫面相似,左手邊是功能視窗,可以檢視檔案與其他功能;,右上方是檔案編輯畫面,可以進行檔案編輯,撰寫程式進行 AWS SDK 操作;右下方則是終端命令列介面,可以輸入指令,進行 AWS CLI 操作。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510NU2ttIc1z4.png
圖 3. AWS Cloud9 IDE

在下方的終端輸入以下指令,取得實驗所需要的資源,可以在左上角看到已下載的檔案。

git clone https://github.com/yehchitsai/AIoTnAWSCloud

https://ithelp.ithome.com.tw/upload/images/20240902/20129510LIwpNdnTBP.png
圖 4. 取得實驗所需要的資源

使用 AWS CLI 建立 S3 儲存貯體

輸入以下 AWS CLI 指令,用來建立 S3 儲存貯體,將 BUCKET_NAME 改為自己所要建立的 S3 儲存貯體名稱。
aws s3api create-bucket --bucket BUCKET_NAME

AWS CLI 說明指令:
aws [options] <command> <subcommand> [parameters]

  • aws:呼叫 AWS CLI,這需要安裝 AWS Command Line Interface (AWS CLI)工具才能夠使用,而 AWS cloud 9 環境已經事先安裝好,所以開發者可以不用安裝。
  • s3api:對應到 AWS CLI 語法中的 command,內容是 AWS 的資源,s3api就是指 S3 的資源。
  • create-bucket:對應到 AWS CLI 語法中的 subcommand,內容是對 command 中的資源進行何種操作,這裡是建立 S3 儲存貯體。
  • --bucket aiotnawscloud0821:對應到 AWS CLI 語法中的 parameters,內容是S3 儲存貯體的名稱命名為 aiotnawscloud0821

而回傳值是建立儲存貯體的名稱。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510mIU77hp5Fb.png
圖 5. 使用 AWS CLI 指令建立 S3 儲存貯體

注意:儲存貯體的名稱是全球唯一的,所以每個人都要取不同的名稱。

使用Python SDK為儲存貯體設定儲存貯體策略

打開 s3_security_policy.json 檔案,將 BUCKET_NAME 改成自己所建立的儲存貯體的名稱,MY_PUBLIC_IP 則是要上網查找自己電腦的公開ip,這可能會跟自己電腦上所設定的ip不同,因為大多數情況,上網都是多人共用一個公開ip,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20240902/201295102qkCGQL8UO.png
圖 6. 查找自己電腦的公開 IP

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::BUCKET_NAME/*",
                "arn:aws:s3:::BUCKET_NAME"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "MY_PUBLIC_IP/32"
                }
            }
        }
    ]
}

修改完畢後,接著修改 permissions.pyBUCKET_NAME 自己所建立的儲存貯體的名稱,接著執行,就可以在新的儲存貯體上設定政策,讓自己的電腦可以用靜態網站的方式使用 S3。

import boto3
import json
import pathlib

s3_client = boto3.client("s3", region_name="us-east-1")
bucket_name = "BUCKET_NAME"
current_path = str(pathlib.Path(__file__).parent.resolve())
policy_file = open(current_path + "/dataset/s3_security_policy.json", "r")


s3_client.put_bucket_policy(
    Bucket = bucket_name,
    Policy = policy_file.read()
)

https://ithelp.ithome.com.tw/upload/images/20240902/20129510SIxDOFs3nE.png
圖 7. 使用 Python SDK 為儲存貯體設定儲存貯體策略

接著可以到 S3 控制台,檢視 S3 儲存貯體策略。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510QuuRxaf0xg.png
圖 8. 檢視 S3 儲存貯體策略

將物件上傳到儲存貯體以建立網站

將物件上傳到儲存貯體以建立網站,將 BUCKET_NAME 改為自己建立的 S3 儲存貯體名稱。

aws s3 cp AIoTnAWSCloud/lab/website s3://BUCKET_NAME/ --recursive --cache-control "max-age=0"

https://ithelp.ithome.com.tw/upload/images/20240902/20129510A2IbEbCEjV.png
圖 9. 物件上傳到儲存貯體

測試網站的訪問

在 S3 儲存貯體中到找到首頁 show_s3_image.html ,點選後在屬性頁籤找到物件 URL,複製起來打開一個空白網頁。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510jF9W0KnzlN.png
圖 10. 取得首頁的進入網址

貼上網址後,就可以檢視網頁成果,沒有圖片只有文字。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510CyUIOaECJb.png
圖 11. 檢視網頁

撰寫 AWS Lambda

建立函數

進入 Lambda 控制台,建立一個新的 AWS Lambda 函數,配置如下:

  • 函數名稱: API2Lambda (可以自定)
  • 執行時間: Python 3.12
  • 執行角色:使用現有角色, LabRole (這個角色可以使用大多數 Learner Lab 中的資源)

https://ithelp.ithome.com.tw/upload/images/20240902/20129510uSpGK7WuBa.png
圖 12. 建立 AWS Lambda 函數

編碼

在 Lambda 函數中撰寫要運行的程式碼,在程式碼頁簽程式碼來源撰寫測試的程式。
因為這次程式的功能為讀取用戶透過 HTTP POST 請求所傳遞過來的圖片,圖片內容已經事先轉換成 base64 格式,收到 base64 格式的字符串後,轉換成圖片,並上傳到 S3 ,代碼如下:

BUCKET_NAME 改為自己所建立的 S3 儲存貯體名稱。

import json
import base64
import boto3

# 存放圖片的 S3 存儲桶 
output_bucket = 'BUCKET_NAME'
# 存放在 S3 存儲桶中的檔案名稱
s3_key_value = 'apigateway2S3.jpg'
s3_client = boto3.client('s3')

def lambda_handler(event, context):
  requestMethod = event['httpMethod']
  # HTTP 請求方式為 POST 才做後續處理
  if requestMethod=='POST':
    # 將上傳的 JSON 字符串轉換成字典
    requestBody = json.loads(event['body'])
    # 將上傳的 base64 字符串轉換成字組,再轉換成 binary 格式
    image_64_decode = base64.decodebytes(requestBody['key'].encode())
    # 上傳到 S3 存儲桶
    response = s3_client.put_object(
        Body=image_64_decode,
        Bucket=output_bucket,
        Key=f'{s3_key_value}',
    )
    s3_url = 'https://' + output_bucket + '.s3.amazonaws.com/' + s3_key_value
    return {
        'statusCode': 200,
        'body': s3_url
    }
  else:
  # HTTP 請求方式非 POST 回傳錯誤
    return {
        'statusCode': 200,
        'body': 'method error'
    }

https://ithelp.ithome.com.tw/upload/images/20240902/20129510hzNQEStC9b.png
圖 13. AWS Lambda 函數程式碼

部署

編寫完成程式碼之後,由於還沒有部署,無法進行測試或者調用。部署類似於將程式碼同步到 Lambda 函數中,部署程式碼,點擊 Deploy,撰寫完程式碼之後需要部署程式碼,之後才能進行測試。

添加 API Gateway 觸發器

在 Lambda 主畫面上方找到添加觸發器按鈕,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510TcBEhBJUiV.png
圖 14. 在 Lambda 主畫面中進行添加觸發器

進入添加觸發器畫面,配置如下:

添加觸發器

  • 觸發器配置: API Gateway
  • Intent: Create a new API
  • API type: HTTP API
  • Security: Open
    Additional settings
  • API name: API2Lambda-API
  • Deployment stage: default
  • 勾選 Cross-origin resource sharing (CORS)

https://ithelp.ithome.com.tw/upload/images/20240902/20129510bRGvegbSsE.png
圖 15. 在添加觸發器畫面中進行 API Gateway 配置

添加觸發器後可以在配置中查看觸發器的結果,取得 API 終端節點,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20240902/201295109y7RcBzVMB.png
圖 16. 取得 API 終端節點

生成測試資料-base64

因為程式碼需要讀取使用者傳來的資料,所以需要用 POSTMAN 來傳圖片資料,而圖片資料需要轉換成 base64 格式,所以需要撰寫額外的程式碼來進行轉換,進入 Cloude9 打開 encode_image.py 程式,它會將 python 目錄中的 yehchitsai.jpg 圖片進行編碼,並將結果存在 base64.txt

# convert base64 to image 
import base64
import pathlib

current_path = str(pathlib.Path(__file__).parent.resolve())
image = open(current_path + '/images/yehchitsai.jpg', 'rb')
image_read = image.read()
image_64_encode = base64.encodebytes(image_read)
# print(image_64_encode)
image_encode_file = open(f'{current_path}/base64.txt','w')
image_encode_file.write(str(image_64_encode))
image_encode_file.close()

執行完上述程式後,它會將base64的資料存在base64.txt中,複製 b' 這裡的資料,不包含前後單引號 '

https://ithelp.ithome.com.tw/upload/images/20240902/20129510dJe37ezPsi.png
圖 17. 取得圖片的base64編碼

測試 / 調用 - 使用 Postman 進行測試

接著使用常見的 API 測試軟件來進行測試,在本機端打開 Postman,並輸入相關的配置。

  • URL 網址:將上圖中的 API endpoint 輸入
  • 請求方法: POST
  • Body: 選擇 raw,格式為 JSON

接著點擊送出 Send 就得到完整的請求信息響應 (Response),即為上傳到 S3 的網址。
https://ithelp.ithome.com.tw/upload/images/20240902/20129510LStdOffT4t.png
圖 18. 取得圖片的 S3 的網址

確認圖片內容

進入 Cloud9 修改 show_s3_image.html 網頁所指定的圖片所在位置,改為圖片的 S3 的網址,並將網頁上傳到 S3,如下圖所示。

將該網頁上傳到 S3 上,在下方的終端畫面輸入以下指令,將 BUCKET_NAME 改為自己建立的 S3 儲存貯體名稱。:
aws s3 cp AIoTnAWSCloud/lab/website/show_s3_image.html s3://BUCKET_NAME/

https://ithelp.ithome.com.tw/upload/images/20240902/20129510IGUYZpTg42.png
圖 19. 修改網頁所指定的圖片所在位置

再重新檢視一次網頁,就可以看到上傳的圖片內容了。

https://ithelp.ithome.com.tw/upload/images/20240902/20129510NyJ8sYXmfq.png
圖 20. 重新檢視網頁

參考資料


上一篇
D25-實驗:使用 GET 方法查詢資料 - Lambda
下一篇
D27-Amazon DynamoDB
系列文
在AWS上進行物聯網與人工智慧實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言