---
title: Upload file to server
tags: GCS
---
# Upload file to server
## 需求
- project cover 需要上傳圖片,並且要能將上傳的圖片顯示在頁面上
## 討論
1. 目前 tms 是透過套件 multiparty 來實現上傳功能,沒有一隻 API 專門處理,是否需要另開 API 上傳檔案
- 好處: 如未來又有需要上傳檔案,可減少重複的 code
- 未來變更上傳套件,只需要改一隻 API 即可
> 未來有什麼需要上傳檔案?
> 按照目前的設計好像沒有了
2. 是否需要另外在 google cloud storage 儲存檔案,或是另外開一台 disk 儲存
- GCS 好處: 資料自動具有多份的備份,具有完整的資料保護機制
## k8s 現況

- 目前只有透過 NFS(Network File System) 做 pm2 log 的儲存 [可以參考這裡](https://gitlab.com/fio.io/tms/-/blob/dev/scripts/install-pm2-logrotate.sh)
- 如果需要儲存其他東西,可能需要再加開一顆硬碟,透過 NFS 來存取
## 成本效能比較
- 實作成本(錢 and 時間)
- cloud sorage 比較便宜 (GCS 勝
- 有 SDK 已經串好,可以馬上套用 VS 新開一個 disk 透過 NFS 儲存 實作時間不明 (GCS 勝?
- 效能
- 上傳到 tms 再上傳到 GCS vs 上傳到 tms 結束 ( disk 勝
- 顯示圖片可以透過公開 GCS 路徑 vs 直接顯示 ( disk 險勝
### disk


### cloud storage


https://cloud.google.com/storage/pricing?hl=zh-tw
## 研究筆記
- GCS and AWS s3
- GCS and AWS s3 皆有 bucket, 概念也幾乎一樣
- 在試做的 opencert 裡將 bucket 分成 `fio-service-dev` / `fio-service-prod`
- 定義公開的路徑 `https://storage.cloud.google.com/${BUCKET_NAME}/${OBJECT_NAME}`
> GCS: Cloud Storage 使用平面命名空間運行,這意味著文件夾實際上不會存在於Cloud Storage 中。
> 如果您在存儲桶 your-bucket 中創建名為 folder1/file.txt 的對象,則該對象的路徑為your-bucket/folder1/file.txt,但沒有名為 folder1 的文件夾;字符串 folder1 是對象名稱的一部分。
>
> AWS: 概念與 GCS 一樣 , Amazon S3 supports buckets and objects, and there is no hierarchy. However, by using prefixes and delimiters in an object key name,
> the Amazon S3 console and the AWS SDKs can infer hierarchy and introduce the concept of folders.
> [AWS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html)

- Google 建議如果是給不同人看,推薦將 bucket 分開
- 可能會將 bucket 分成: 公開的 bucket 與 不公開的 bucket
- 如果需要將資料切換是否公開,可以用 copy or move 的功能,將檔案從公開的 bucket 轉到不公開的 bucket
- GCS 與 AWS S3 都有此功能
- 切換至不同儲存位置可能會有額外頻寬的費用 e.g. 亞洲 => 歐洲
[GCS copy](https://googleapis.dev/nodejs/storage/latest/File.html#copy)
[GCS move](https://cloud.google.com/storage/docs/copying-renaming-moving-objects#storage-move-object-nodejs)
https://cloud.google.com/storage/docs/access-control/?hl=zh-tw&_ga=2.204249872.-1238561395.1660620188&_gac=1.116408692.1663053632.CjwKCAjw1ICZBhAzEiwAFfvFhK5aGUUGi8xJQIUS-XIC9MB0-EBC5VX5xE4Zd_bnSa2baYCxtoXCpBoCVKcQAvD_BwE
## 遇到的問題
1. 權限設定: bucket 可以統一設定公開與不公開 vs 不設統一權限,單一檔案設定公開與不公開
- 單一檔案設定 public 權限
- 好處: 不用分過多的 bucket
- 壞處: 每個檔案不同權限,較難管理,不易看出哪些是公開,哪些是不公開,上傳時需要多 call 一個 function
- 由 bucket 統一設定 public 權限
- 好處: 單一 bucket 就是決定 public or private 很直覺
- 壞處: 依照每個環境需要多開兩個 bucket,數量會比較多(預計會多兩個 bucket 而已
#### 結論: 使用 bucket 統一設定權限, bucket 過多並不影響效能,GCS 也沒有限制 bucket,方便管理比較重要
2. folder 依照功能來分類資料 vs 簡單分類 分成跟 project 相不相關
- 依照功能來分類資料
- 好處:
- 想要轉移特定功能的資料時可以透過整個 folder 一起轉移
- 壞處:
- 需要多定義 folder 如何命名 e.g. /nft
- 依照跟 project 相不相關分類資料
- 好處:
- 只需要知道跟 project 相不相關即可上傳到對應的 folder
> FiO 有很多功能會要保存資料嗎? 沒有
> 什麼時候會需要轉移資料? 公開轉到不公開,GCS 轉到 AWS
> 會常發生嗎? 目前不會發生
#### 結論: 依照跟 project 相不相關分類資料
- 以下為 GCS 畫面

## 規劃
- 打算寫成一個 module,寫 FiO 上傳檔案的邏輯,未來可以使用此模組來減少重複的 code
- 上傳功能模組功能:
- 上傳到哪個 storage(GCS, AWS S3, disk...)
- 定義上傳路徑到哪個 bucket and folder
- upload / download
- ~~是否要刪除前一個檔案 e.g. project cover or 大頭貼~~
### Cloud storage 檔案架構
#### Bucket
- 會將 cloud storage 的 bucket 分成 4 個,以環境跟公開不公開作為區分
- fio-service-dev-public
- fio-service-dev-private
- fio-service-prod-public
- fio-service-prod-private
- 上傳到 disk 就直接將 bucket 名稱設定成資料夾名稱,未來當作 k8s 儲存位置的指向 // 先不實作
#### folder
- 分成 projects / general
### 虛擬碼
```=javascript
class StorageService {
construct(storage, folderKey, isPublic){
this.storage = storage;
this.bucketName = getBucketName(isPublic)
// or
if(storage === 'gcs') {
this.storage = new GCS();
} else if (storage == 's3') {
this.storage = new S3();
} else {
throw error
}
this.bucketName = getBucketName(isPublic)
}
}
getBucketName(isPublic) {
check isPublic and env
return BucketName;
}
upload (filePath, isOnly, id) {
if (isOnly === true) {
用 id 改檔名
filePath = newFilePath
}
this.storage.upload(filePath, bucketName, folderName);
}
download (url) {
this.storage.download(url);
}
```