Utilitários do Amazon S3 - AWS SDK para Go v2

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Utilitários do Amazon S3

Gerentes de transferência do Amazon S3

Os gerenciadores de upload e download do Amazon S3 podem dividir objetos grandes, para que possam ser transferidos em várias partes, paralelamente. Isso facilita a retomada das transferências interrompidas.

Gerenciador de upload do Amazon S3

O gerenciador de upload do Amazon S3 determina se um arquivo pode ser dividido em partes menores e carregado paralelamente. Você pode personalizar o número de carregamentos paralelos e o tamanho das partes enviadas.

O exemplo a seguir usa o Amazon S3 Uploader para carregar um arquivo. UploaderO uso é semelhante à s3.PutObject() operação.

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, })

Opções de configuração

Ao instanciar uma Uploader instância usando NewUploader, você pode especificar várias opções de configuração para personalizar como os objetos são carregados. As opções são substituídas fornecendo um ou mais argumentos para. NewUploader Essas opções incluem:

  • PartSize— Especifica o tamanho do buffer, em bytes, de cada peça a ser carregada. O tamanho mínimo por peça é de 5 MiB.

  • Concurrency— Especifica o número de peças a serem carregadas em paralelo.

  • LeavePartsOnError— Indica se as peças enviadas com sucesso devem ser deixadas no Amazon S3.

O Concurrency valor limita o número simultâneo de carregamentos de peças que podem ocorrer em uma determinada Upload chamada. Esse não é um limite global de simultaneidade de clientes. Ajuste os valores Concurrency de configuração PartSize e para encontrar a configuração ideal. Por exemplo, sistemas com conexões de alta largura de banda podem enviar peças maiores e mais carregamentos em paralelo.

Por exemplo, seu aplicativo é configurado Uploader com uma configuração Concurrency de5. Se seu aplicativo então chamar Upload de duas goroutines diferentes, o resultado serão uploads de peças 10 simultâneos (2 goroutines * 5). Concurrency

Atenção

Espera-se que seu aplicativo limite as chamadas simultâneas Upload para evitar o esgotamento dos recursos do aplicativo.

Abaixo está um exemplo para definir o tamanho padrão da peça durante a Uploader criação:

uploader := manager.NewUploader(client, func(u *Uploader) { u.PartSize = 10 * 1024 * 1024, // 10 MiB })

Para obter mais informações Uploader e suas configurações, consulte Uploader na Referência da AWS SDK para Go API.

PutObjectInput Campo corporal (io. ReadSeeker versus io.Reader)

O Body campo da s3.PutObjectInput estrutura é um io.Reader tipo. No entanto, esse campo pode ser preenchido com um tipo que satisfaça tanto a io.ReaderAt interface io.ReadSeeker quanto a fim de melhorar a utilização dos recursos do aplicativo no ambiente host. O exemplo a seguir cria o tipo ReadSeekerAt que satisfaz as duas interfaces:

type ReadSeekerAt interface { io.ReadSeeker io.ReaderAt }

Para io.Reader tipos, os bytes do leitor devem ser armazenados em buffer na memória antes que a peça possa ser carregada. Quando você aumenta o Concurrency valor de PartSize or, a memória (RAM) necessária para o Uploader aumenta significativamente. A memória necessária é de aproximadamente PartSize* Concurrency. Por exemplo, especificar 100 MB para PartSize e 10 paraConcurrency, requer pelo menos 1 GB.

Como um io.Reader tipo não pode determinar seu tamanho antes de ler seus bytes, Uploader não é possível calcular quantas partes serão carregadas. Consequentemente, Uploader pode atingir o limite de upload do Amazon S3 de 10.000 partes para arquivos grandes se você definir um valor PartSize muito baixo. Se você tentar carregar mais de 10.000 peças, o upload será interrompido e retornará um erro.

Para body valores que implementam o ReadSeekerAt tipo, o Uploader não armazena o conteúdo do corpo na memória antes de enviá-lo para o Amazon S3. Uploadercalcula o número esperado de peças antes de fazer o upload do arquivo para o Amazon S3. Se o valor atual de PartSize exigir mais de 10.000 peças para carregar o arquivo, Uploader aumente o valor do tamanho da peça para que menos peças sejam necessárias.

Tratamento de uploads com falha

Se um upload para o Amazon S3 falhar, por padrão, Uploader usa a operação do Amazon AbortMultipartUpload S3 para remover as partes carregadas. Essa funcionalidade garante que os uploads com falha não consumam o armazenamento do Amazon S3.

Você pode definir como verdadeiro LeavePartsOnError para que Uploader não exclua as partes enviadas com sucesso. Isso é útil para retomar carregamentos parcialmente concluídos. Para operar com peças carregadas, você deve obter o UploadID do upload que falhou. O exemplo a seguir demonstra como usar o tipo manager.MultiUploadFailure de interface de erro para obter o. 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 }

Substituindo as opções do carregador por upload

Você pode substituir as Uploader opções ao chamar Upload fornecendo um ou mais argumentos para o método. Essas substituições são modificações seguras para a concorrência e não afetam os uploads em andamento ou as chamadas subsequentes para o gerente. Upload Por exemplo, para substituir a PartSize configuração de uma solicitação de upload específica:

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 })

Exemplos

Faça upload de uma pasta para o Amazon S3

O exemplo a seguir usa o path/filepath pacote para reunir recursivamente uma lista de arquivos e carregá-los no bucket do Amazon S3 especificado. As chaves dos objetos do Amazon S3 são prefixadas com o caminho relativo do arquivo.

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 }

Gerenciador de downloads

O gerenciador do Amazon S3 Downloader determina se um arquivo pode ser dividido em partes menores e baixado paralelamente. Você pode personalizar o número de downloads paralelos e o tamanho das partes baixadas.

Exemplo: Baixar um arquivo

O exemplo a seguir usa o Amazon S3 Downloader para baixar um arquivo. DownloaderO uso é semelhante ao s3. GetObjectoperação.

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"), })

O downloadFile parâmetro é um io.WriterAt tipo. A WriterAt interface permite Downloader gravar várias partes do arquivo em paralelo.

Opções de configuração

Ao instanciar uma Downloader instância, você pode especificar opções de configuração para personalizar como os objetos são baixados:

  • PartSize— Especifica o tamanho do buffer, em bytes, de cada parte a ser baixada. O tamanho mínimo por peça é de 5 MB.

  • Concurrency— Especifica o número de peças a serem baixadas paralelamente.

O Concurrency valor limita o número simultâneo de downloads de peças que podem ocorrer em uma determinada Download chamada. Esse não é um limite global de simultaneidade de clientes. Ajuste os valores Concurrency de configuração PartSize e para encontrar a configuração ideal. Por exemplo, sistemas com conexões de alta largura de banda podem receber peças maiores e mais downloads em paralelo.

Por exemplo, seu aplicativo é configurado Downloader com um Concurrency de5. Seu aplicativo então chama Download de duas goroutines diferentes, o resultado será downloads 10 simultâneos de partes (2 goroutines * 5). Concurrency

Atenção

Espera-se que seu aplicativo limite as chamadas simultâneas Download para evitar o esgotamento dos recursos do aplicativo.

Para obter mais informações sobre Downloader suas outras opções de configuração, consulte Manager.downloader na Referência da API. AWS SDK para Go

Substituindo as opções do downloader por download

Você pode substituir as Downloader opções ao chamar Download fornecendo um ou mais argumentos funcionais para o método. Essas substituições são modificações simultâneas seguras e não afetam os uploads em andamento ou as Download chamadas subsequentes para o gerente. Por exemplo, para substituir a PartSize configuração de uma solicitação de upload específica:

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 })
Exemplos
Baixe todos os objetos em um bucket

O exemplo a seguir usa paginação para reunir uma lista de objetos de um bucket do Amazon S3. Em seguida, ele baixa cada objeto em um arquivo local.

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

GetBucketRegioné uma função utilitária para determinar a localização AWS da região de um bucket do Amazon S3. GetBucketRegionpega um cliente Amazon S3 e o usa para determinar a localização do bucket solicitado na AWS partição associada à região configurada do cliente.

Por exemplo, para encontrar a região do bucketamzn-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)

Se não GetBucketRegion for possível resolver a localização de um Bucket, a função retornará um tipo de BucketNotFounderro, conforme mostrado no exemplo.

Entrada de streaming inexplorável

Para operações de API como PutObject eUploadPart, o cliente Amazon S3 espera que o valor do parâmetro de Body entrada implemente a interface IO.Seeker por padrão. A io.Seeker interface é usada pelo cliente para determinar o tamanho do valor a ser carregado e para calcular o hash da carga útil para a assinatura da solicitação. Se o valor do parâmetro de Body entrada não for implementadoio.Seeker, seu aplicativo receberá um erro.

operation error S3: PutObject, failed to compute payload hash: failed to seek body to start, request stream is not seekable

Você pode alterar esse comportamento modificando o método de operação Middleware usando opções funcionais. O APIOptions auxiliar With retorna uma opção funcional para zero ou mais mutadores de middleware. Para desativar o cliente computando o hash da carga útil e usar a assinatura de solicitação de carga não assinada, adicione v4. SwapComputePayloadSHA256ForUnsignedPayloadMiddleware.

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, ))
Atenção

O Amazon S3 exige que o tamanho do conteúdo seja fornecido para todos os objetos carregados em um bucket. Como o parâmetro Body de entrada não implementa a io.Seeker interface, o cliente não poderá calcular o ContentLength parâmetro para a solicitação. O parâmetro deve ser fornecido pelo aplicativo. A solicitação falhará se o ContentLength parâmetro não for fornecido.

Use os SDKs Gerenciador de upload do Amazon S3 para uploads que não possam ser pesquisados e não tenham um tamanho conhecido.