php小編新一在這裡為大家介紹一個高效的方式來處理S3檔下載,以避免耗盡伺服器資源。 S3是亞馬遜提供的可擴展的雲端儲存服務,但在處理大型檔案下載時,傳統的下載方式可能會導致伺服器資源耗盡。本文將介紹一種基於PHP的解決方案,透過分塊下載和串流的方式,有效處理S3檔案下載,提升伺服器效能和使用者體驗。讓我們一起來了解這個方法吧!
我有一個 go-gin 應用程序,它允許在 S3 中上傳和下載多種文件類型。
上傳到 s3 之前的所有檔案均使用 AWS s3cryptoclient、AES GCM 和來自 KMS 的金鑰進行加密。因此,就 s3 儲存桶而言,一切都是二進位的。
我可以使用 getObject 的 SDK 指令將檔案下載到伺服器並解密,然後使用 io.write(tempfile) 將此檔案提供給客戶端下載。
此處的問題 S3 包含大小為 10GB 的文件,並且該伺服器每天將有多個使用者存取。正如我們所看到的,在具有 16GB RAM 的伺服器上寫入臨時檔案也會很快耗盡內存,同時我們還要注意運行此類伺服器的成本。
瓶頸是文件在獲得服務之前需要解密,在這種用例中,S3 預簽名url 就足夠了,儘管解密不是由s3 預簽名url 提供的,除非它是由客戶完成的加密,在我們的案例AWS 正在處理加密,因此解決方案不可行。
有沒有人有任何提示或可能的用例來解決這個問題,我們可以使用 go-gin/NGINX 將檔案直接寫入客戶端。
目前使用者對檔案下載的處理
s3FileStream, _ := s3c.GetBucketItem(&utils.S3ObjectBucketInput{ Bucket: "bucketName", Key: "UserFileName" }) fileBody, err := io.ReadAll(s3FileStream.Body) if err != nil { panic(err.Error()) } fileExtension := s3FileStream.Metadata["X-Amz-Meta-Type"] err = ioutil.WriteFile("file" + *fileExtension, fileBody, 600) // temp file if err != nil { panic(err.Error()) } c.JSON(http.StatusCreated, string(fileBody)) c.Done()
}
一種選擇是將物件直接作為回應正文寫入客戶端:
s3FileStream, _ := s3c.GetBucketItem(&utils.S3ObjectBucketInput{ Bucket: "bucketName", Key: "UserFileName", }) fileExtension := s3FileStream.Metadata["X-Amz-Meta-Type"] c.DataFromReader(http.StatusCreated, 0, "application/data", s3FileStream.Body, map[string]string{"Content-Dispositon": "attachment; filename=" + "file" + *fileExtension}) c.Done()
以上是處理 S3 檔案下載而不耗盡資源的詳細內容。更多資訊請關注PHP中文網其他相關文章!