

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
<a name="sdk-utilities-s3"></a>

## Administradores de transferencias de Amazon S3
<a name="transfer-managers"></a>

 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
<a name="s3-upload-manager"></a>

 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
<a name="configuration-options"></a>

 Al crear una `Uploader` instancia mediante [NewUploader](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#NewUploader), puede especificar varias opciones de configuración para personalizar la forma en que se cargan los objetos. Las opciones se reemplazan al proporcionar uno o varios argumentos a `NewUploader`. 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](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#Uploader) en la referencia de la AWS SDK para Go API. 

#### PutObjectInput Body Field (io). ReadSeeker contra io.Reader)
<a name="putobjectinput-body-field-ioreadseeker-vs-ioreader"></a>

 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
<a name="handling-failed-uploads"></a>

 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
<a name="overriding-uploader-options-per-upload"></a>

 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
<a name="examples"></a>

##### Carga de una carpeta en Amazon S3
<a name="upload-a-folder-to-s3"></a>

 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
<a name="download-manager"></a>

 El administrador [Downloader](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#Downloader) de Amazon S3 determina si un archivo puede dividirse en partes más pequeñas y descargarse en paralelo. Puede personalizar el número de descargas paralelas y el tamaño de las partes descargadas. 

#### Ejemplo: Descarga de un archivo
<a name="example-download-a-file"></a>

 En el ejemplo siguiente se utiliza `Downloader` de Amazon S3 para descargar un archivo. `Downloader`[El uso es similar al s3. GetObject](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#Client.GetObject)operación. 

```
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
<a name="configuration-options-1"></a>

 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](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager/#Downloader) en la referencia de la AWS SDK para Go API. 

#### Reemplazo de opciones de Downloader por descarga
<a name="overriding-downloader-options-per-download"></a>

 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
<a name="examples-1"></a>

##### Descarga de todos los objetos de un bucket
<a name="download-all-objects-in-a-bucket"></a>

 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
<a name="getbucketregion"></a>

 [GetBucketRegion](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#GetBucketRegion)es una función de utilidad para determinar la ubicación AWS regional de un bucket de Amazon S3. `GetBucketRegion`toma 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](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#BucketNotFound)error, como se muestra en el ejemplo. 

## Entrada de transmisión no buscable
<a name="unseekable-streaming-input"></a>

 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.Seeker](https://pkg.go.dev/io#Seeker) de forma predeterminada. El cliente utiliza la interfaz `io.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](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html). 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](middleware.md) del método de operación con opciones funcionales. El APIOptions asistente [With](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#WithAPIOptions) devuelve una opción funcional para cero o más mutadores de middleware. [Para impedir que el cliente calcule el hash de la carga útil y utilice la firma de solicitud de carga útil [sin firmar, añada la versión v4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html). SwapComputePayloadSHA256ForUnsignedPayloadMiddleware](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws/signer/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,
))
```

**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](#s3-upload-manager) para aquellas cargas que no se puedan buscar y que no tengan una longitud conocida. 