如何透過 AWS Lambda 處理圖片?(2)- How to modify image by AWS Lambda ?(2)

處理了上傳內容的問題,再來要解決實際處理內容,讓圖片可以被加工

Whien

--

|閱讀目錄

|將請求的上傳內容處理為可用內容

從第一篇文章中所取得的請求內容後,multipart/form-data 不是實際檔案的內容,而是提供此檔案屬性的說明,所以需要將真實檔案內容提取出來,以下是嘗試將內容提取出來的程式碼內容

本篇文章就直接進入實作解釋,如果要了解標準可以查看 multipart/form-data rfc 7578 標準

|如何解析 multipart/form-data 內容

從內容中可以得知只能從 binary 下手,因此需要一個一個去檢查。

在 multipart/form-data 中,發送請求至後端伺服器時,會帶著標準規範的 boundary head,通常 boundary 會是一串隨機的字串

boundary=--{隨機字串}

這個表示在 multipart/form-data 中的所有資料要透過哪一串隨機字串來做分割,如果沒有 boundary 那應用開發人員就無法知道要如何分辨這些請求來源資料的開頭結束

|切割 boundary 拿到 body 圖片資料

從上面已經提供的程式中可以看到幾個預設的變數與常數,在電腦世界中訊息資料是很笨拙且固定的,所以 rfc7578 中定義了每一行所表示的意思,以及如何切割這些內容,接下來就一起來了解如何記錄這些內容。

Lambda 拿到資料後,因為 body 是一串原始資料,所以必須要一個一個檢查,關鍵的兩個常數 RET 與 NEWLINE

  • RET(0x0d)
  • NEWLINE(0x0a)

RET 與 NEWLINE 是已經定義好的行為,在辨識原始資料時,只要遇到 ascii 為 0x0d 或 0x0a 就表示游標回到行的最前面下一行的意思。

|其他變數的作用 — ( linecount )

linecount 變數負責記錄目前已經處理到第幾行,當每次遇到 RET(0x0d) 與 NEWLINE(0x0a) 時,就表示換行了,這時候就將 linecount 往上計算,即可知道目前的行數狀態。

|其他變數的作用 — ( obj )

obj 拿來做真實每一行所分析出來的結果內容,在 rfc7578 都詳細定義了每一行的內容,只要知道目前的 linecount 而 body 也是按照標準,這麼來即可分配正確的內容至 obj 中,以便後續應用使用。

|其他變數的作用 — ( tmpline )

tmpline 負責將每一行所拿到的每個字保存起來,直到遇到 RET(0x0d) 與 NEWLINE(0x0a)就放置至對的 obj linecount 中。

|其他變數的作用 — ( buffer )

buffer 緩存是到最後 data 的內容時,負責暫時儲存資料的地方,因為圖片是一堆沒有可辨識性的一串內容,所以需要一個一個 byte 的記錄下來,不像以上幾個變數可以直接辨識為 ascii 中的某個字。

在 linecount 4 與 linecount 5 中可以發現有 buffer.push(NEWLINE) 的情形,主要是解決在處理圖片過程中發現了一些 byte 處理後發生異常狀況加上的 workaround。

|嘗試使用 parser 的輸出結果

const incomeBody = Buffer.from('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',
'base64'
)
const obj = parse(incomeBody){
boundary: '------WebKitFormBoundaryByAs4Jyusp8qfyCk\r',
'content-disposition': 'Content-Disposition: form-data; name="file"; filename="æ\x88ªå\x9C\x96 2021-07-21 ä¸\x8Bå\x8D\x887.16.25.png"\r',
'content-type': 'Content-Type: image/png\r',
data: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 64 00 00 00 30 08 06 00 00 00 e7 fd df b5 00 00 01 45 69 43 43 50 49 43 43 20 50 72 6f 66 69 ... 4178 more bytes>,
lastboundary: '------WebKitFormBoundaryByAs4Jyusp8qfyCk--\r'
}

|使用 canvas 來處理圖片

安裝 canvas

yarn add canvas

|調整圖片內容

最後得到的 parse64Data 即可拿來做各種利用,例如儲存為 s3 檔案,或是直接回應結果至前端應用進行額外操作。

看似美好,但最後為什麼不能用呢?

因為 AWS Lambda 有一些限制 ..

Invocation payload 6 MB (synchronous) 256 KB (asynchronous),memory allocation 也有一定的限制,徹底破滅了我的理想,雖然便宜但也不是可以隨便使用,現在用戶手機圖片隨意拍就上傳,很容易就超過上限,在實際應用場景中,也無法將用戶的圖片任意壓縮…,最後只好告吹了。

但中途也確實學習到了很多,包含 AWS API Gateway 的客制化設定,AWS Lambda Layer 的使用(這又可以打成一篇分享),處理相容性問題,整整大概花了一天半的工作時間才將此嘗試完成。

|Last Mentions

  1. 使用 canvas 套件時,要注意幾件事情,因為 canvas 內部有使用 c++ binary 的套件,所以會導致在 macOS 打包的內容 packages 在 Lambda Linux OS 中無法起作用,因為是不同的核心,這需要自行做打包檔(canvas github document 文件中有說明)或是直接透過 Google 搜尋去找到已經打包完整的 Linux 版本。
  2. 因為打包後的檔案大小會過大,建議要再使用 Lambda Layer 去拆分 packages 才不會導致 AWS Lambda 不給使用。
  3. 如果要處理一般小兒雜的圖片是很推薦使用的,要處理大型圖片檔案就不太適合了,尤其在 timeout 方面也有限制,雖然普通來說不太會超過最大 timeout 時間,但圖片處理時間複雜後也難免會遇到此問題。

--

--

Whien

遨遊在硬體與軟體世界中,對於計算機一切事物都充滿好奇及熱情。