本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
Amazon S3 公用程式
Amazon S3 Transfer Manager
Amazon S3 上傳和下載管理員可以分解大型物件,因此可以多個部分平行傳輸。這可讓您輕鬆恢復中斷的傳輸。
Amazon S3 上傳管理員
Amazon S3 上傳管理員會判斷檔案是否可以分割成較小的部分並平行上傳。您可以自訂平行上傳的數量和上傳組件的大小。
下列範例使用 Amazon S3 Uploader
上傳檔案。使用 Uploader
類似於 s3.PutObject()
操作。
import "context" import "github.com/aws/aws-sdk-go-v2/config" import "github.com/aws/aws-sdk-go-v2/service/s3" import "github.com/aws/aws-sdk-go-v2/feature/s3/manager" // ... cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Printf("error: %v", err) return } client := s3.NewFromConfig(cfg) uploader := manager.NewUploader(client) result, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{ Bucket: aws.String("
amzn-s3-demo-bucket
"), Key: aws.String("my-object-key
"), Body: uploadFile, })
組態選項
當您使用 NewUploaderUploader
執行個體時,您可以指定數個組態選項來自訂物件的上傳方式。選項是透過提供一或多個引數給 來覆寫NewUploader
。這些選項包括:
-
PartSize
– 指定要上傳的每個部分的緩衝區大小,以位元組為單位。每個組件的大小下限為 5 MiB。 -
Concurrency
– 指定要平行上傳的組件數量。 -
LeavePartsOnError
– 指出是否要在 Amazon S3 中保留成功上傳的組件。
Concurrency
值會限制指定Upload
呼叫可能發生的並行部分上傳數目。這不是全域用戶端並行限制。調整 PartSize
和 Concurrency
組態值以尋找最佳組態。例如,具有高頻寬連線的系統可以平行傳送較大的部分和更多上傳。
例如,您的應用程式Uploader
使用 Concurrency
的 設定 5
。如果您的應用程式接著Upload
從兩個不同的 goroutine 呼叫 ,則結果為10
並行部分上傳 (2 個 goroutines * 5)Concurrency
。
警告
預期您的應用程式會將並行呼叫限制為 Upload
,以防止應用程式資源耗盡。
以下是在Uploader
建立期間設定預設組件大小的範例:
uploader := manager.NewUploader(client, func(u *Uploader) { u.PartSize = 10 * 1024 * 1024, // 10 MiB })
如需 Uploader
及其組態的詳細資訊,請參閱 適用於 Go 的 AWS SDK API 參考中的上傳者
PutObjectInput 內文欄位 (io.ReadSeeker 與 io.Reader)
s3.PutObjectInput
結構的 Body
欄位是 io.Reader
類型。不過,此欄位可以填入同時滿足 io.ReadSeeker
和 io.ReaderAt
界面的類型,以改善主機環境的應用程式資源使用率。下列範例會建立滿足兩個界面ReadSeekerAt
的類型:
type ReadSeekerAt interface { io.ReadSeeker io.ReaderAt }
對於 io.Reader
類型,讀取器的位元組必須在記憶體中緩衝,才能上傳組件。當您增加 PartSize
或 Concurrency
值時, 所需的記憶體 (RAM) 會大幅Uploader
增加。所需的記憶體約為 PartSize
* Concurrency
。例如,為 指定 100 MB,為 PartSize
指定 10Concurrency
, 至少需要 1 GB。
由於 io.Reader
類型無法在讀取位元組之前判斷其大小,因此 Uploader
無法計算上傳的組件數量。因此,如果您設定PartSize
太低,大型檔案的 Amazon S3 上傳限制Uploader
可以達到 10,000 個部分。如果您嘗試上傳超過 10,000 個組件,上傳會停止並傳回錯誤。
對於實作 ReadSeekerAt
類型的body
值, Uploader
不會先緩衝記憶體中的內文內容,再將其傳送至 Amazon S3。 會在將檔案上傳至 Amazon S3 之前Uploader
計算預期的組件數量。如果目前的 值PartSize
需要超過 10,000 個組件才能上傳檔案, 會Uploader
增加組件大小值,因此需要較少的組件。
處理失敗的上傳
如果上傳至 Amazon S3 的 依預設失敗, Uploader
會使用 Amazon S3 AbortMultipartUpload
操作來移除上傳的部分。此功能可確保失敗的上傳不會使用 Amazon S3 儲存體。
您可以LeavePartsOnError
設為 true,讓 Uploader
不會刪除成功上傳的組件。這對於繼續部分完成的上傳非常有用。若要在上傳的組件上操作,您必須取得失敗上傳UploadID
的 。下列範例示範如何使用manager.MultiUploadFailure
錯誤界面類型來取得 UploadID
。
result, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{ Bucket: aws.String("
amzn-s3-demo-bucket
"), Key: aws.String("my-object-key
"), Body: uploadFile, }) output, err := u.upload(input) if err != nil { var mu manager.MultiUploadFailure if errors.As(err, &mu) { // Process error and its associated uploadID fmt.Println("Error:", mu) _ = mu.UploadID() // retrieve the associated UploadID } else { // Process error generically fmt.Println("Error:", err.Error()) } return }
每次上傳覆寫上傳者選項
您可以透過提供一或多個引數給 方法Upload
來覆寫呼叫 時Uploader
的選項。這些覆寫是並行安全的修改,不會影響持續上傳或後續Upload
呼叫管理員。例如,若要覆寫特定上傳請求的PartSize
組態:
params := &s3.PutObjectInput{ Bucket: aws.String("
amzn-s3-demo-bucket
"), Key: aws.String("my-key
"), Body: myBody, } resp, err := uploader.Upload(context.TODO(), params, func(u *manager.Uploader) { u.PartSize = 10 * 1024 * 1024, // 10 MiB })
範例
將資料夾上傳至 Amazon S3
下列範例使用 path/filepath
套件以遞迴方式收集檔案清單,並將其上傳至指定的 Amazon S3 儲存貯體。Amazon S3 物件的金鑰會以檔案的相對路徑做為字首。
package main import ( "context" "log" "os" "path/filepath" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/feature/s3/manager" "github.com/aws/aws-sdk-go-v2/service/s3" ) var ( localPath string bucket string prefix string ) func init() { if len(os.Args) != 4 { log.Fatalln("Usage:", os.Args[0], "<local path> <bucket> <prefix>") } localPath = os.Args[1] bucket = os.Args[2] prefix = os.Args[3] } func main() { walker := make(fileWalk) go func() { // Gather the files to upload by walking the path recursively if err := filepath.Walk(localPath, walker.Walk); err != nil { log.Fatalln("Walk failed:", err) } close(walker) }() cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Fatalln("error:", err) } // For each file found walking, upload it to Amazon S3 uploader := manager.NewUploader(s3.NewFromConfig(cfg)) for path := range walker { rel, err := filepath.Rel(localPath, path) if err != nil { log.Fatalln("Unable to get relative path:", path, err) } file, err := os.Open(path) if err != nil { log.Println("Failed opening file", path, err) continue } defer file.Close() result, err := uploader.Upload(context.TODO(), &s3.PutObjectInput{ Bucket: &bucket, Key: aws.String(filepath.Join(prefix, rel)), Body: file, }) if err != nil { log.Fatalln("Failed to upload", path, err) } log.Println("Uploaded", path, result.Location) } } type fileWalk chan string func (f fileWalk) Walk(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() { f <- path } return nil }
下載管理員
Amazon S3 Downloader
範例:下載檔案
下列範例使用 Amazon S3 Downloader
下載檔案。使用 Downloader
類似於 s3.GetObject
import "context" import "github.com/aws/aws-sdk-go-v2/aws" import "github.com/aws/aws-sdk-go-v2/config" import "github.com/aws/aws-sdk-go-v2/service/s3" import "github.com/aws/aws-sdk-go-v2/feature/s3/manager" // ... cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Println("error:", err) return } client := s3.NewFromConfig(cfg) downloader := manager.NewDownloader(client) numBytes, err := downloader.Download(context.TODO(), downloadFile, &s3.GetObjectInput{ Bucket: aws.String("
amzn-s3-demo-bucket
"), Key: aws.String("my-key
"), })
downloadFile
參數是 io.WriterAt
類型。WriterAt
界面可讓 平行Downloader
寫入檔案的多個部分。
組態選項
當您執行個體化Downloader
執行個體時,您可以指定組態選項來自訂物件的下載方式:
-
PartSize
– 指定要下載的每個部分的緩衝區大小,以位元組為單位。每個組件的大小下限為 5 MB。 -
Concurrency
– 指定要平行下載的組件數目。
Concurrency
值會限制指定Download
呼叫可同時執行的部分下載數量。這不是全域用戶端並行限制。調整 PartSize
和 Concurrency
組態值以尋找最佳組態。例如,具有高頻寬連線的系統可以平行接收更大的部分和更多的下載。
例如,您的應用程式Downloader
會使用 Concurrency
的 來設定 5
。然後,您的應用程式Download
會從兩個不同的 goroutine 呼叫 ,結果將是10
並行部分下載 (2 個 goroutines * 5)Concurrency
。
警告
預期您的應用程式會將並行呼叫限制為 Download
,以防止應用程式資源耗盡。
如需 Downloader
及其其他組態選項的詳細資訊,請參閱 適用於 Go 的 AWS SDK API 參考中的 manager.Downloader
每次下載覆寫下載程式選項
您可以在呼叫 時Download
,透過提供一或多個功能引數給 方法來覆寫Downloader
選項。這些覆寫是並行安全修改,不會影響持續上傳或後續Download
呼叫管理員。例如,若要覆寫特定上傳請求的PartSize
組態:
params := &s3.GetObjectInput{ Bucket: aws.String("
amzn-s3-demo-bucket
"), Key: aws.String("my-key
"), } resp, err := downloader.Download(context.TODO(), targetWriter, params, func(u *manager.Downloader) { u.PartSize = 10 * 1024 * 1024, // 10 MiB })
範例
下載儲存貯體中的所有物件
下列範例使用分頁從 Amazon S3 儲存貯體收集物件清單。然後,它會將每個物件下載到本機檔案。
package main import ( "context" "fmt" "log" "os" "path/filepath" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/feature/s3/manager" "github.com/aws/aws-sdk-go-v2/service/s3" ) var ( Bucket = "
amzn-s3-demo-bucket
" // Download from this bucket Prefix = "logs/" // Using this key prefix LocalDirectory = "s3logs" // Into this directory ) func main() { cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Fatalln("error:", err) } client := s3.NewFromConfig(cfg) manager := manager.NewDownloader(client) paginator := s3.NewListObjectsV2Paginator(client, &s3.ListObjectsV2Input{ Bucket: &Bucket, Prefix: &Prefix, }) for paginator.HasMorePages() { page, err := paginator.NextPage(context.TODO()) if err != nil { log.Fatalln("error:", err) } for _, obj := range page.Contents { if err := downloadToFile(manager, LocalDirectory, Bucket, aws.ToString(obj.Key)); err != nil { log.Fatalln("error:", err) } } } } func downloadToFile(downloader *manager.Downloader, targetDirectory, bucket, key string) error { // Create the directories in the path file := filepath.Join(targetDirectory, key) if err := os.MkdirAll(filepath.Dir(file), 0775); err != nil { return err } // Set up the local file fd, err := os.Create(file) if err != nil { return err } defer fd.Close() // Download the file using the AWS SDK for Go fmt.Printf("Downloading s3://%s/%s to %s...\n", bucket, key, file) _, err = downloader.Download(context.TODO(), fd, &s3.GetObjectInput{Bucket: &bucket, Key: &key}) return err }
GetBucketRegion
GetBucketRegionGetBucketRegion
會取得 Amazon S3 用戶端,並使用它來判斷與用戶端設定區域相關聯之 AWS 分割區中請求的儲存貯體位置。
例如,若要尋找儲存貯體 的區域
:amzn-s3-demo-bucket
cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Println("error:", err) return } bucket := "
amzn-s3-demo-bucket
" region, err := manager.GetBucketRegion(ctx, s3.NewFromConfig(cfg), bucket) if err != nil { var bnf manager.BucketNotFound if errors.As(err, &bnf) { log.Printf("unable to find bucket %s's Region\n", bucket) } else { log.Println("error:", err) } return } fmt.Printf("Bucket %s is in %s region\n", bucket, region)
如果 GetBucketRegion
無法解析儲存貯體的位置,則 函數會傳回 BucketNotFound
不可查看的串流輸入
對於 PutObject
和 等 API 操作UploadPart
,Amazon S3 用戶端預期Body
輸入參數的值預設會實作 io.Seekerio.Seeker
界面來判斷要上傳的值長度,以及運算請求簽章的承載雜湊。如果Body
輸入參數值未實作 io.Seeker
,您的應用程式將收到錯誤。
operation error S3: PutObject, failed to compute payload hash: failed to seek body to start, request stream is not seekable
您可以使用中介軟體功能選項修改操作方法的 ,以變更此行為。WithAPIOptions
resp, err := client.PutObject(context.TODO(), &s3.PutObjectInput{ Bucket: &bucketName, Key: &objectName, Body: bytes.NewBuffer([]byte(`example object!`)), ContentLength: 15, // length of body }, s3.WithAPIOptions( v4.SwapComputePayloadSHA256ForUnsignedPayloadMiddleware, ))
警告
Amazon S3 要求為所有物件上傳至儲存貯體的內容長度提供。由於Body
輸入參數未實作io.Seeker
界面,用戶端將無法計算請求的 ContentLength
參數。參數必須由應用程式提供。如果未提供 ContentLength
參數,請求將會失敗。
將 SDK 的 Amazon S3 上傳管理員用於無法尋找且沒有已知長度的上傳。