[Third party service Note] - 第一次使用 AWS S3 上傳圖片就上手

Introduction & 前言

AWS S3

今年最後一篇文章就獻給 AWS S3(下稱 S3) 了,這篇文章用來記錄如何將自己的圖片上傳至第三方儲存空間,並且可以取得瀏覽網址。

這篇對於 S3 不會有太深的介紹以及講解,主要用來介紹並且筆記,如果你也在思考自己的專案想要將圖片放在哪裡,是專案主機呢?還是 S3?這邊並不會做過多的討論以及比較,但如果你已經確定要將圖片放置在 S3 那就可以參考接下來的內容!


什麼是 AWS(Amazon Simple Storage Service) S3

雲

相信會看到這篇文章的,有 87% 大概都知道 S3 是什麼了,但這邊還是在稍微再提一下。

S3 就是一個儲存服務,也是雲端服務,好處在於該設定以及安全性問題,AWS 都已經幫你想好了,你只需要上傳檔案,以及使用他們現有的 API,比如 **瀏覽檔案、刪除檔案…**等等,由 亞馬遜網路服務公司(Amazon Web Services) 推出的服務。

你可能會想單純檔案瀏覽上傳並下載其實我們放到 imgur.com 就好了呀,其實使用 S3 的好處還有在 存取權授 這邊,也是在 S3 上設定即可,也可以設定開發人員,透過指派的方式,可給予每個指派人員唯一金鑰去做存取動作。


加碼場 Multer

由於我們會透過 form-data 從前端傳送圖片檔案到後端,再由後端上傳至 S3,在接收檔案以及查看檔案是否符合規格時,我們可以使用這個套件,方便我們做檢查及上傳的輔助橋樑。

如果有興趣透過 Node.js 傳送圖片至 S3 的人可以先到 Multer GitHub 瀏覽一下,如果沒興趣只想知道怎麼開通 S3 服務最後一節可以跳過。


開始使用 S3 服務

S3 憑證

如同 Google Analytics 一樣,S3 只是 AWS 的眾多服務之一,您必須先到 AWS 去註冊帳號密碼。

註冊結束後進入 **AWS 管理控制台**,

這和其他第三方服務一樣,您需要有 Token 這類的東西才能夠使用它們的服務,而 AWS 需要 訪問密鑰ID(Access ID)私有訪問密鑰(Secret Access key) 您才能使用這項服務。

AWS 管理控制台

點選 My Security Credentials

創建新的訪問密鑰

點選 訪問密鑰(訪問密鑰 ID 和秘密訪問密鑰)(Access keys(access key ID and secret access key)) 之後緊接著點選 **創建新的訪問密鑰(Create New Access Key)**。

拿到新的 Access ID 及 Access Key

跳出彈窗代表您已經建立成功,然後將您的 訪問密鑰ID(Access ID)私有訪問密鑰(Secret Access key) 記下或是點選 下載密鑰文件(Download Key File) 下載 .csv 文件。

新增一個 Bucket

S3

接下然我們要創建一個 S3服務儲存桶,點選左上角的 Services 你會發現 AWS 的眾多服務,看到左邊第一排的 S3 點進去。

點擊新增S3儲存桶

然後點選新**增儲存桶(Create New Bucket)**。

地區選擇

之後輸入 儲存桶(Bucket) 的名稱,然後地區建議選擇離你當下比較近的位子,像筆者住在台灣,所以就會選擇 亞太地區(東京)ap-northeast-1亞太地區(新加坡)ap-southeast-1 其中之一,有道是越近越快。不過這邊不討論這個問題。

阻止公有訪問設定

然後下方的 阻止公有訪問設定 請一定要勾掉,不然之後圖片上傳完成後,如果想要訪問,就會出現下方的內容。

Access 權限錯誤

如果忘記勾選掉,之後進去儲存桶後也可以到 權限 去點選編輯然後勾掉。

阻止公有訪問設定 權限設定

因為我們只是要上傳圖片,並且讓所有人都能看見,所以這邊必須勾掉!

上傳圖片

最後就可以上傳圖片啦,上傳完成後就可以點擊圖片名稱,

預覽圖片

儲存桶進入後還可以在資料夾,檔案就可以分類了。

到這邊就大功告成啦!如果有興趣如何透過 Node.js 接收檔案並上傳到 S3 可以接著繼續看,如果沒興趣也可以直接跳到結論囉。


Multer

開始前先介紹筆者的環境。

  • node v-v12.16.1

  • express v-4.16.1

先說說為什麼會用這個套件,因為在 Express 4.16 版本以前跟之後讀取 Form Data 的方式不太一樣,筆者上網爬文過後發現這個套件可以檢查檔案格式或是限制檔案大小,並且可以方便抓取檔案,所以就入坑了。

事前準備

首先必須安裝套件以及上傳圖片至 S3 必須使用的套件(關於 Node 環境如何建立可以參考我的另篇文章 [NodeJS Become A Full Stack Developer] — Express、Router 及 EJS 入門淺談,這邊先預設您已經安裝好且環境都設定好了)。

1
$ npm i aws-sdk multer --save

抓取上傳檔案

其實官方教學已經寫得差不多,但這次我把抓取檔案的流程寫在 Middleware,一來方便管理,二來乾淨清爽。

中介層

然後在裡面謝上相關程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const multer = require('multer');

// 圖片上傳
const profileUpload = multer({
limit: {
// 限制上傳檔案的大小為 1MB
fileSize: 1000000
},
fileFilter(req, file, cb) {
// 只接受三種圖片格式
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
cb(null, false);
}
cb(null, true);
}
})

module.exports = {
profileUpload
};

引入套件並且檢查檔案大小及格式。

接著在路由加上您的仲介層:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var express = require('express');
var router = express.Router();

const { profileUpload } = require('../../../middleware/file');
const fileController = require('../../../controllers/file');
const fileSchema = require('./schema');

const apiBasePath = `/file`


/* GET users listing. */
router
.post(`${apiBasePath}/upload-file`, profileUpload.single('profile_img'), fileSchema.request.uploadSchema, fileController.upload)

module.exports = router;

這邊只要使用 profileUpload.single('File Name or Form Data Key') 就可以進入剛剛的仲介層然後檢查檔案,如果不想拆這麼細,其實也可以向官方介紹的一樣,寫在一起。

接著只要在想要讀取檔案的地方使用 req.file 就可以拿到相關資訊。

上傳至 S3

重頭戲就是從 Node.js 上傳檔案至 S3 啦,先在我們需要上傳檔案的地方引入套件。

1
2
3
4
5
6
7
const AWS = require('aws-sdk');

// 把上面新增完 儲存桶(Bucket) 拿到的那個檔案裡面的 Access Key ID 及 Secret Access Key 填上
const s3 = new AWS.S3({
accessKeyId: 'xxx-xxx-xxx-xxx',
secretAccessKey: 'xxx-xxx-xxx-xxx-xxx'
});

然後按照官方的 API 文件,繼續下面的程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
const params = {
Bucket: 'test-bucket/user-image', // 相簿位子
Key: 'test-1', // 你希望儲存在 S3 上的檔案名稱
Body: req.file.buffer, // 檔案
ACL: 'public-read', // 檔案權限
ContentType: req.file.mimetype // 副檔名
};

s3.upload(params, function(err, data) {
if (err) console.log(err, err.stack);
else console.log('Bucket Created Successfully', data.Location);
}

請記得關於 儲存桶(Bucket) 的資料夾呼叫還有使用方式,都是加上斜線,像上面的範例就是 test-bucket 這個 儲存桶(Bucket) 裡面的資料夾 user-image

上傳成功

上傳成功後如果 console.log(data) 可以看見更多資訊,只是 data.Location 就是我們要用來預覽的檔案,如果點選網址變成下載,請記得一定要檢查你的副檔名稱是不是正確的(Ex:.jpg|.jpeg|.png)。

相關上傳、刪除、瀏覽的 API 可以參考 從瀏覽器上傳相片至 Amazon S3,這邊也有詳盡的介紹。

本地新增刪除儲存桶

如果您不想要線上建立 儲存桶(Bucket) 其實也可以本地建立,有興趣可以參考 Uploading Files to AWS S3 with Node.js 的下半篇文章,或是參考官方的 API Document


Conclusion & 結論

會有這篇文章的起因為筆者目前正在實踐開始寫程式兩年自己的目標計畫,完成前後端電商的 Side Project,但由於剛好親朋好友有個需求可以寫成 Side Project 就改成寫預約系統了,這次剛好有使用者上傳大頭貼的部分,就研究了一直聽同事在說的 S3(為什麼沒挑 GCP 呢,因為聽說 GCP 比較貴)。

而同事也有跟我說其實放專案本機即可,但秉持著碰到就研究是最好的學習,所以就一頭栽進去啦,其實整個過程挺好玩的,並沒有想像中複雜。

其實在寫這篇文章的時候已經 2021/1/1 了,但還是想說說這一年來的簡短感想,除了中途迷惘過一陣子,這段時間程式帶給我的不止是成就感也有更多的快樂,我想只要是工程師就面臨不了工作及生活上的分配以及取捨,我想這還是工程師要面臨最大的難題,所以筆者認為適時的補充知識(任何方面)及學習是不可或缺的,但當工作及學習已經融入你的生活當中,可能還是不太好的(筆者得想法,請不要砲我),在 2020 我相信大家都深深的體會到時間多麽珍貴,以及珍惜的重要,有的時候放下你身邊的工作及忙碌的事情,好好的陪伴家人、朋友,有些東西失去了、沒了,就再也回不去了。

講起來好像滿感傷的,其實筆者這一年過的還是很開心,要謝的人很多很多,親人、愛人、朋友、上司、老闆 還有 家裡那兩條狗,願我們不止 2021 還有以後的每一年都會越來越好、越來越棒!

也再次謝謝已在程式碼打混多年的各位前輩們,還有剛接觸不久的你們,不管是哪一點也好,對這個世界以及人們都繼續推使他們更便利更進步,我想這也是我喜歡這個行業的原因之一,我想幫助更多的人,讓自己是付出的一端。

揮別 2020 歡迎 2021。


參考網站