Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Utilidades de Amazon S3
Administradores de transferencias de Amazon S3
Los administradores de carga y descarga de Amazon S3 pueden dividir objetos grandes para transferirlos en varias partes, en paralelo. Esto facilita la reanudación de transferencias interrumpidas.
Administrador de cargas de Amazon S3
El administrador de cargas de Amazon S3 determina si un archivo puede dividirse en partes más pequeñas y cargarse en paralelo. Puede personalizar el número de cargas paralelas y el tamaño de las partes que se cargan.
En el ejemplo siguiente se utiliza el elemento Uploader de Amazon S3 para cargar un archivo: El uso de Uploader es similar a la operación 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, })
Opciones de configuración
Al crear una Uploader instancia mediante NewUploaderNewUploader. Entre estas opciones se incluyen las siguientes:
-
PartSize: especifica el tamaño del búfer, en bytes, de cada una de las partes que se van a cargar. El tamaño mínimo por parte es de 5 MiB. -
Concurrency: especifica el número de partes que se van a cargar en paralelo. -
LeavePartsOnError: indica si las partes cargadas correctamente se deben dejar en Amazon S3.
El valor Concurrency limita el número simultáneo de cargas de partes que pueden producirse durante una llamada a Upload determinada. No se trata de un límite de simultaneidad de clientes global. Ajuste los valores de configuración PartSize y Concurrency para encontrar la configuración óptima. Por ejemplo, los sistemas con conexiones de gran ancho de banda pueden enviar partes más grandes y más cargas en paralelo.
Por ejemplo, la aplicación configura Uploader con un ajuste de Concurrency establecido en 5. Si, a continuación, la aplicación llama a Upload desde dos rutinas de Go diferentes, el resultado son 10 cargas de partes simultáneas (2 rutinas de Go por 5 Concurrency).
aviso
Se espera que su aplicación limite las llamadas simultáneas a Upload para evitar el agotamiento de los recursos de la aplicación.
A continuación, se muestra un ejemplo para establecer el tamaño predeterminado de las partes durante la creación de Uploader:
uploader := manager.NewUploader(client, func(u *Uploader) { u.PartSize = 10 * 1024 * 1024, // 10 MiB })
Para obtener más información Uploader y sus configuraciones, consulta Uploader
PutObjectInput Body Field (io). ReadSeeker contra io.Reader)
El campo Body de la estructura s3.PutObjectInput es un tipo io.Reader. Sin embargo, este campo se puede rellenar con un tipo que cumpla tanto con la interfaz io.ReadSeeker como con io.ReaderAt para mejorar el uso de los recursos de las aplicaciones en el entorno de host. En el ejemplo siguiente, se crea el tipo ReadSeekerAt que cumple con ambas interfaces:
type ReadSeekerAt interface { io.ReadSeeker io.ReaderAt }
En el caso de los tipos io.Reader, los bytes del lector deben almacenarse en la memoria del búfer antes de que pueda cargarse la parte. Al aumentar el valor PartSize o Concurrency, la memoria (RAM) necesaria para el elemento Uploader aumenta considerablemente. La memoria necesaria es de aproximadamente PartSize por Concurrency. Por ejemplo, si se especifican 100 MB para PartSize y un valor de diez para Concurrency, se requiere al menos 1 GB.
Como un tipo io.Reader no puede determinar su tamaño antes de leer sus bytes, Uploader no puede calcular cuántas partes se cargarán. En consecuencia, Uploader puede alcanzar el límite de carga de Amazon S3 de 10 000 partes para archivos de gran tamaño si establece el valor PartSize demasiado bajo. Si intenta cargar más de 10 000 partes, la carga se detendrá y devolverá un error.
En el caso de los valores body que implementan el tipo ReadSeekerAt, Uploader no almacena en la memoria del búfer el contenido del cuerpo antes de enviarlo a Amazon S3. Uploader calcula el número de partes previsto antes de cargar el archivo en Amazon S3. Si el valor actual de PartSize requiere más de 10 000 partes para cargar el archivo, Uploader aumenta el valor de tamaño de las partes de modo que se requieran menos.
Gestión de cargas con errores
Si se produce un error de carga en Amazon S3, de forma predeterminada, Uploader utiliza la operación AbortMultipartUpload de Amazon S3 para eliminar las partes cargadas. Esta funcionalidad garantiza que las cargas con errores no consuman el almacenamiento de Amazon S3.
Puede establecer LeavePartsOnError en true para que Uploader no elimine las partes que se hayan cargado correctamente. Esto resulta útil para reanudar las cargas completadas parcialmente. Para poder actuar en las partes ya cargadas, debe obtener el valor UploadID de la carga con errores. En el ejemplo siguiente se muestra cómo utilizar el tipo de interfaz de error manager.MultiUploadFailure para obtener el valor 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 }
Reemplazo de opciones de cargador por carga
Puede reemplazar las opciones de Uploader al llamar a Upload. Para ello, proporcione uno o varios argumentos al método. Estos reemplazos son modificaciones seguras para el uso simultáneo y no afectan a las cargas en curso ni a las llamadas de Upload posteriores al administrador. Por ejemplo, si desea reemplazar la configuración de PartSize para una solicitud de carga 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 })
Ejemplos
Carga de una carpeta en Amazon S3
En el ejemplo siguiente se utiliza el paquete path/filepath para recopilar de forma recursiva una lista de archivos y cargarlos en el bucket de Amazon S3 especificado. Las claves de los objetos de Amazon S3 llevan como prefijo la ruta relativa del archivo.
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 }
Administrador de descargas
El administrador Downloader
Ejemplo: Descarga de un archivo
En el ejemplo siguiente se utiliza Downloader de Amazon S3 para descargar un archivo. DownloaderEl uso es similar al 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"), })
El parámetro downloadFile es un tipo io.WriterAt. La interfaz WriterAt permite a Downloader escribir varias partes del archivo en paralelo.
Opciones de configuración
Al crear una instancia de Downloader, puede especificar opciones de configuración para personalizar la forma en que se descargan los objetos:
-
PartSize: especifica el tamaño del búfer, en bytes, de cada una de las partes que se van a descargar. El tamaño mínimo por parte es de 5 MB. -
Concurrency: especifica el número de partes que se van a descargar en paralelo.
El valor Concurrency limita el número simultáneo de descargas de partes que pueden producirse durante una llamada a Download determinada. No se trata de un límite de simultaneidad de clientes global. Ajuste los valores de configuración PartSize y Concurrency para encontrar la configuración óptima. Por ejemplo, los sistemas con conexiones de gran ancho de banda pueden recibir partes más grandes y más descargas en paralelo.
Por ejemplo, la aplicación configura Downloader con un ajuste de Concurrency establecido en 5. Si, a continuación, la aplicación llama a Download desde dos rutinas de Go diferentes, el resultado son 10 descargas de partes simultáneas (2 rutinas de Go por 5 Concurrency).
aviso
Se espera que su aplicación limite las llamadas simultáneas a Download para evitar el agotamiento de los recursos de la aplicación.
Para obtener más información sobre Downloader sus demás opciones de configuración, consulte Manager.Downloader
Reemplazo de opciones de Downloader por descarga
Puede reemplazar las opciones de Downloader al llamar a Download. Para ello, proporcione uno o varios argumentos funcionales al método. Estos reemplazos son modificaciones seguras para el uso simultáneo y no afectan a las cargas en curso ni a las llamadas de Download posteriores al administrador. Por ejemplo, si desea reemplazar la configuración de PartSize para una solicitud de carga 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 })
Ejemplos
Descarga de todos los objetos de un bucket
En el ejemplo siguiente se utiliza la paginación para recopilar una lista de objetos desde un bucket de Amazon S3. A continuación, se descarga cada objeto en un archivo 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
GetBucketRegionGetBucketRegiontoma un cliente Amazon S3 y lo usa para determinar la ubicación del bucket solicitado dentro de la AWS partición asociada a la región configurada del cliente.
Por ejemplo, para encontrar la región del bucket : 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)
Si GetBucketRegion no puede resolver la ubicación de un bucket, la función devuelve un tipo de BucketNotFound
Entrada de transmisión no buscable
En el caso de operaciones de API como PutObject y UploadPart, el cliente de Amazon S3 espera que el valor del parámetro de entrada Body implemente la interfaz io.Seekerio.Seeker a fin de determinar la longitud del valor que se va a cargar y calcular el hash de carga útil para la firma de solicitud. Si el valor del parámetro de entrada Body no implementa io.Seeker, la aplicación recibirá un error.
operation error S3: PutObject, failed to compute payload hash: failed to seek body to start, request stream is not seekable
Para cambiar este comportamiento, modifique el Middleware del método de operación con opciones funcionales. El APIOptions asistente With
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, ))
aviso
Amazon S3 requiere que se proporcione la longitud del contenido para todos los objetos cargados en un bucket. Como el parámetro de entrada Body no implementa la interfaz io.Seeker, el cliente no podrá calcular el parámetro ContentLength para la solicitud. La aplicación debe proporcionar el parámetro. Si no se proporciona el parámetro ContentLength se producirá un error en la solicitud.
Use los SDK Administrador de cargas de Amazon S3 para aquellas cargas que no se puedan buscar y que no tengan una longitud conocida.