本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
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過低, Uploader可以達到大型檔案 10,000 個部分的 Amazon S3 上傳限制。如果您嘗試上傳超過 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 }
Download Manager
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 上傳管理員 用於無法尋找且沒有已知長度的上傳。