在開發中後期遇到 multipart/form-data 的問題時,在評估後我們選擇改用 TUS (The Upload Server)。TUS 是一個開放的、獨立於 GraphQL 的協定,專為可靠的、可恢復的檔案上傳而設計。它的核心理念,就是將大型檔案拆分成可管理的區塊,並提供斷點續傳的能力。
TUS 在 GraphQL 架構中的角色並非直接融入 GraphQL 的請求處理,而是作為一個外部的、專門的檔案上傳服務,而 GraphQL API 則扮演協調者 (Coordinator) 的角色,尤其在檔案完成上傳後處理業務邏輯方面。
第一步:Client 與 TUS 伺服器互動 (HTTP POST / PATCH / HEAD)
客戶端: 當使用者準備上傳檔案時,Client 會使用 TUS library(例如 tus-js-client)與 TUS 伺服器進行互動。這個過程會由 TUS library 自動處理:
- Client 會先向 tusd 送出一個 HTTP POST request,初始化一個新的上傳資源。
- tusd 會回應一個唯一的、用於該檔案上傳的 TUS 上傳 URL (例如 https://tus-server.example.com/uploads/your-upload-id)。
- 接著,Client 會將檔案分割成多個資料區塊 (chunks),並透過一系列的 HTTP PATCH 請求將這些資料區塊逐一上傳到這個 TUS 上傳 URL。
- 過程中,TUS client 會檢查 Upload-Offset 確保從正確的位置續傳。
- 若上傳中斷,client 會利用 HEAD 請求查詢當前進度,然後從上次中斷的地方恢復上傳。
tusd: 在此互動過程中,tusd 會獨立接收並組裝檔案資料,同時維護上傳 session 的狀態。
第二步:GraphQL 接收上傳完成通知並執行後續邏輯 (GraphQL Mutation)
客戶端: 當 TUS client 確認檔案已成功上傳到 TUS 伺服器後,client 會再次向 GraphQL API 發送一個 Mutation request。這個 Mutation 會攜帶 TUS 服務為該檔案產生的唯一識別符 fileId,以及任何需要與該檔案關聯的 metadata。
GraphQL API (後端): 接收到這個完成通知後,會執行一系列的處理:
- 它會根據客戶端提供的 fileId 驗證檔案是否確實已成功上傳並存在。
- 接著,它會執行與該檔案相關的後續業務邏輯,例如:將檔案關聯到使用者帳戶,產生縮圖,更新資料庫紀錄,或觸發其他後端處理任務。
- 最終,GraphQL API 會回傳操作是否成功的結果。