跳至主要內容
Skip to content

檔案上傳系統設計 (4) —— 效能優化與大檔案處理

在完成基礎與安全性後,我們要面對的是「真實世界的挑戰」。使用者可能會上傳一張 10MB 的 4K 高畫質照片,但你的網頁其實只需要顯示一個 200px 的頭像;或者使用者在火車上傳檔案,網路斷斷續續,導致大檔案傳到一半毀掉。

這一篇,我們來聊聊如何讓檔案上傳系統「既快又穩」。


一、 圖片處理與自動壓縮

使用者不一定懂得縮圖,但後端一定要。如果你的網站直接加載原始圖片,不僅浪費頻寬,載入速度也會慢到氣死使用者。

建議流程:

  1. 接收原始檔:先安全存入。
  2. 非同步處理:利用後端套件(如 Node.js 的 Sharp)生成不同尺寸的縮圖(Thumbnail, Medium, Large)。
  3. 格式優化:將檔案轉換為 WebPAVIF 格式,體積通常比 JPG/PNG 小 30% 以上。
javascript
const sharp = require("sharp");

async function optimizeImage(inputPath, outputPath) {
  await sharp(inputPath)
    .resize(800) // 寬度固定 800px,高度自動等比例
    .webp({ quality: 80 }) // 轉為 WebP 並設定品質
    .toFile(outputPath);
}

二、 秒傳機制 (Deduplication)

「秒傳」聽起來很神奇,其實原理非常單純:不重複儲存內容相同的檔案。

實作原理:

  1. 前端在傳送檔案前,先計算檔案的內容 Hash(例如 SHA-256)。
  2. 後端先檢查資料庫:是否存在相同的 Hash?
  3. 如果存在,直接在資料庫新增一筆關聯紀錄,指向同一個物理路徑,並回傳「成功」。

TIP

對於使用者來說,他按「上傳」後瞬間就完成了,這就是極致的體驗優化。


三、 大檔案斷點續傳 (Resumable Uploads)

當檔案達到數百 MB 甚至 GB 級別時,一次性上傳的風險極高。

核心策略:分塊上傳 (Chunking)

  1. 切片:前端利用 Blob.slice() 將檔案切成若干個小塊(例如每塊 2MB)。
  2. 編號與上傳:每一塊帶上 chunkIndexuploadId 依序或併發傳給後端。
  3. 狀態追蹤:後端接收並存入臨時目錄,並在資料庫/快取紀錄「已接收第幾塊」。
  4. 合併:當最後一塊傳完後,後端將所有分片「按順序」拼回去,並做最終 Hash 校驗。

優點:

  • 斷點續傳:如果傳到第 50 塊斷線,下次只需從第 51 塊開始傳。
  • 防止記憶體溢出:即使是超大檔案,後端每次處理的也只是 2MB 的小分片。

總結

高效能的檔案系統具備以下特質:

  1. 智慧壓縮:不浪費一公克的頻寬。
  2. 秒傳效應:節省重複的儲存空間。
  3. 穩定傳輸:面對大檔案與劣質網路環境,依然能靠分塊與斷點續傳保持韌性。

下一篇,我們將邁向本系列的終點站:邁向雲端架構 (S3 / GCS),學習如何擺脫單機伺服器的限制。


️ 進階挑戰

計算大檔案的 Hash 其實很耗 CPU 資源。如果是 10GB 的檔案,前端計算 Hash 可能會讓瀏覽器卡死,你該如何解決這個問題?


延伸閱讀與資源

← 上一章:安全性防禦與驗證 | 返回專案首頁 | 下一章:邁向雲端架構