

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Utilitas Amazon S3
<a name="sdk-utilities-s3"></a>

## Manajer Transfer Amazon S3
<a name="transfer-managers"></a>

 Pengelola unggahan dan unduhan Amazon S3 dapat memecah objek besar, sehingga dapat ditransfer dalam beberapa bagian, secara paralel. Ini memudahkan untuk melanjutkan transfer yang terputus. 

### Manajer Unggahan Amazon S3
<a name="s3-upload-manager"></a>

 Manajer unggahan Amazon S3 menentukan apakah file dapat dibagi menjadi bagian-bagian yang lebih kecil dan diunggah secara paralel. Anda dapat menyesuaikan jumlah upload paralel dan ukuran bagian yang diunggah. 

 Contoh berikut menggunakan Amazon S3 `Uploader` untuk mengunggah file. `Uploader`Penggunaannya mirip dengan `s3.PutObject()` operasi. 

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

#### Opsi konfigurasi
<a name="configuration-options"></a>

 Saat membuat instance menggunakan `Uploader` instance [NewUploader](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#NewUploader), Anda dapat menentukan beberapa opsi konfigurasi untuk menyesuaikan cara objek diunggah. Opsi diganti dengan memberikan satu atau lebih argumen ke. `NewUploader` Pilihan ini meliputi: 
+  `PartSize`- Menentukan ukuran buffer, dalam byte, dari setiap bagian untuk meng-upload. Ukuran minimum per bagian adalah 5 MiB. 
+  `Concurrency`- Menentukan jumlah bagian untuk meng-upload secara parallel. 
+  `LeavePartsOnError`— Menunjukkan apakah akan meninggalkan bagian yang berhasil diunggah di Amazon S3. 

 `Concurrency`Nilai membatasi jumlah bersamaan dari bagian upload yang dapat terjadi untuk panggilan tertentu`Upload`. Ini bukan batas konkurensi klien global. Tweak nilai `PartSize` dan `Concurrency` konfigurasi untuk menemukan konfigurasi yang optimal. Misalnya, sistem dengan koneksi bandwidth tinggi dapat mengirim bagian yang lebih besar dan lebih banyak unggahan secara paralel. 

 Misalnya, aplikasi Anda mengonfigurasi `Uploader` dengan `Concurrency` pengaturan. `5` Jika aplikasi Anda kemudian memanggil `Upload` dari dua goroutine yang berbeda, hasilnya adalah unggahan bagian `10` bersamaan (2 goroutine\$1 5). `Concurrency` 

**Awas**  
 Aplikasi Anda diharapkan membatasi panggilan bersamaan `Upload` untuk mencegah kehabisan sumber daya aplikasi. 

 Di bawah ini adalah contoh untuk mengatur ukuran bagian default selama `Uploader` pembuatan: 

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

 Untuk informasi selengkapnya tentang `Uploader` dan konfigurasinya, lihat [Pengunggah di Referensi](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#Uploader) AWS SDK untuk Go API. 

#### PutObjectInput Bidang Tubuh (io. ReadSeeker vs io.reader)
<a name="putobjectinput-body-field-ioreadseeker-vs-ioreader"></a>

 `Body`Bidang `s3.PutObjectInput` struct adalah `io.Reader` tipe. Namun, bidang ini dapat diisi dengan jenis yang memenuhi `io.ReaderAt` antarmuka `io.ReadSeeker` dan antarmuka untuk meningkatkan pemanfaatan sumber daya aplikasi dari lingkungan host. Contoh berikut menciptakan tipe `ReadSeekerAt` yang memenuhi kedua antarmuka: 

```
type ReadSeekerAt interface {
    io.ReadSeeker
    io.ReaderAt
}
```

 Untuk `io.Reader` jenis, byte pembaca harus di-buffer dalam memori sebelum bagian dapat diunggah. Ketika Anda meningkatkan `PartSize` atau `Concurrency` nilai, memori yang diperlukan (RAM) untuk `Uploader` meningkat secara signifikan. Memori yang dibutuhkan kira-kira *`PartSize`*\$1 *`Concurrency`*. Misalnya, menentukan 100 MB untuk `PartSize` dan 10 untuk`Concurrency`, membutuhkan setidaknya 1 GB. 

 Karena suatu `io.Reader` tipe tidak dapat menentukan ukurannya sebelum membaca byte-nya, `Uploader` tidak dapat menghitung berapa banyak bagian yang akan diunggah. Akibatnya, `Uploader` dapat mencapai batas unggah Amazon S3 10.000 bagian untuk file besar jika Anda mengatur `PartSize` terlalu rendah. Jika Anda mencoba mengunggah lebih dari 10.000 bagian, unggahan berhenti dan mengembalikan kesalahan. 

 Untuk `body` nilai yang mengimplementasikan `ReadSeekerAt` tipe, `Uploader` tidak menyangga isi isi isi dalam memori sebelum mengirimnya ke Amazon S3. `Uploader`menghitung jumlah bagian yang diharapkan sebelum mengunggah file ke Amazon S3. Jika nilai saat ini `PartSize` membutuhkan lebih dari 10.000 bagian untuk mengunggah file, `Uploader` tingkatkan nilai ukuran bagian sehingga lebih sedikit bagian yang diperlukan. 

#### Menangani Unggahan Gagal
<a name="handling-failed-uploads"></a>

 Jika unggahan ke Amazon S3 gagal, secara default, `Uploader` gunakan operasi Amazon `AbortMultipartUpload` S3 untuk menghapus bagian yang diunggah. Fungsionalitas ini memastikan bahwa unggahan yang gagal tidak menggunakan penyimpanan Amazon S3. 

 Anda dapat mengatur `LeavePartsOnError` ke true sehingga `Uploader` tidak menghapus bagian yang berhasil diunggah. Ini berguna untuk melanjutkan unggahan yang sebagian selesai. Untuk beroperasi pada bagian yang diunggah, Anda harus mendapatkan `UploadID` unggahan yang gagal. Contoh berikut menunjukkan bagaimana menggunakan jenis antarmuka `manager.MultiUploadFailure` kesalahan untuk mendapatkan. `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
}
```

#### Mengganti Opsi Pengunggah Per Unggahan
<a name="overriding-uploader-options-per-upload"></a>

 Anda dapat mengganti `Uploader` opsi saat memanggil `Upload` dengan memberikan satu atau beberapa argumen ke metode. Penggantian ini adalah modifikasi aman konkurensi dan tidak memengaruhi unggahan yang sedang berlangsung, atau panggilan berikutnya ke manajer. `Upload` Misalnya, untuk mengganti `PartSize` konfigurasi untuk permintaan unggahan tertentu: 

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

#### Contoh
<a name="examples"></a>

##### Unggah Folder ke Amazon S3
<a name="upload-a-folder-to-s3"></a>

 Contoh berikut menggunakan `path/filepath` paket untuk mengumpulkan daftar file secara rekursif dan mengunggahnya ke bucket Amazon S3 yang ditentukan. Kunci objek Amazon S3 diawali dengan jalur relatif file. 

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

### Pengelola Unduhan
<a name="download-manager"></a>

 [Manajer Amazon S3 Downloader](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#Downloader) menentukan apakah file dapat dibagi menjadi bagian-bagian yang lebih kecil dan diunduh secara paralel. Anda dapat menyesuaikan jumlah unduhan paralel dan ukuran bagian yang diunduh. 

#### Contoh: Download File
<a name="example-download-a-file"></a>

 Contoh berikut menggunakan Amazon S3 `Downloader` untuk mengunduh file. Menggunakan `Downloader` mirip dengan [s3. GetObject](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#Client.GetObject)operasi. 

```
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`Parameternya adalah `io.WriterAt` tipe. `WriterAt`Antarmuka memungkinkan `Downloader` untuk menulis beberapa bagian file secara paralel. 

#### Opsi konfigurasi
<a name="configuration-options-1"></a>

 Saat membuat `Downloader` instance, Anda dapat menentukan opsi konfigurasi untuk menyesuaikan cara objek diunduh: 
+  `PartSize`- Menentukan ukuran buffer, dalam byte, dari setiap bagian untuk men-download. Ukuran minimum per bagian adalah 5 MB. 
+  `Concurrency`- Menentukan jumlah bagian untuk men-download secara paralel. 

 `Concurrency`Nilai membatasi jumlah unduhan bagian bersamaan yang dapat terjadi untuk `Download` panggilan tertentu. Ini bukan batas konkurensi klien global. Tweak nilai `PartSize` dan `Concurrency` konfigurasi untuk menemukan konfigurasi yang optimal. Misalnya, sistem dengan koneksi bandwidth tinggi dapat menerima bagian yang lebih besar dan lebih banyak unduhan secara paralel. 

 Misalnya, aplikasi Anda mengonfigurasi `Downloader` dengan file`Concurrency`. `5` Aplikasi Anda kemudian memanggil `Download` dari dua goroutine yang berbeda, hasilnya akan menjadi unduhan bagian `10` bersamaan (2 goroutine\$1 5). `Concurrency` 

**Awas**  
 Aplikasi Anda diharapkan membatasi panggilan bersamaan `Download` untuk mencegah kehabisan sumber daya aplikasi. 

 Untuk informasi selengkapnya tentang `Downloader` dan opsi konfigurasi lainnya, lihat [Manager.Downloader di Referensi](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager/#Downloader) API. AWS SDK untuk Go 

#### Mengganti Opsi Pengunduh Untuk Unduhan
<a name="overriding-downloader-options-per-download"></a>

 Anda dapat mengganti `Downloader` opsi saat memanggil `Download` dengan memberikan satu atau beberapa argumen fungsional ke metode. Penggantian ini adalah modifikasi aman konkurensi dan tidak memengaruhi unggahan yang sedang berlangsung, atau `Download` panggilan berikutnya ke manajer. Misalnya, untuk mengganti `PartSize` konfigurasi untuk permintaan unggahan tertentu: 

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

##### Contoh
<a name="examples-1"></a>

##### Unduh Semua Objek dalam Ember
<a name="download-all-objects-in-a-bucket"></a>

 Contoh berikut menggunakan pagination untuk mengumpulkan daftar objek dari bucket Amazon S3. Kemudian mengunduh setiap objek ke file lokal. 

```
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)adalah fungsi utilitas untuk menentukan lokasi AWS Wilayah Bucket Amazon S3. `GetBucketRegion`mengambil klien Amazon S3 dan menggunakannya untuk menentukan lokasi Bucket yang diminta dalam AWS Partisi yang terkait dengan Wilayah yang dikonfigurasi klien. 

 Misalnya, untuk menemukan Wilayah untuk 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)
```

 Jika `GetBucketRegion` tidak dapat menyelesaikan lokasi Bucket, fungsi mengembalikan jenis [BucketNotFound](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/feature/s3/manager#BucketNotFound)kesalahan seperti yang ditunjukkan pada contoh. 

## Masukan Streaming yang Tidak Dapat Dicari
<a name="unseekable-streaming-input"></a>

 Untuk operasi API seperti `PutObject` dan`UploadPart`, klien Amazon S3 mengharapkan nilai parameter `Body` input untuk mengimplementasikan antarmuka [io.Seeker secara default.](https://pkg.go.dev/io#Seeker) `io.Seeker`[Antarmuka digunakan oleh klien untuk menentukan panjang nilai yang akan diunggah, dan untuk menghitung hash payload untuk tanda tangan permintaan.](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) Jika nilai parameter `Body` input tidak diterapkan`io.Seeker`, aplikasi Anda akan menerima kesalahan. 

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

 Anda dapat mengubah perilaku ini dengan memodifikasi metode operasi [Middleware](middleware.md) menggunakan opsi fungsional. The [With APIOptions](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#WithAPIOptions) helper mengembalikan opsi fungsional untuk nol atau lebih mutator middleware. [Untuk menonaktifkan klien yang menghitung hash payload dan menggunakan tanda tangan permintaan [Unsigned Payload add 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,
))
```

**Awas**  
 Amazon S3 mengharuskan panjang konten disediakan untuk semua objek yang diunggah ke bucket. Karena parameter `Body` input tidak mengimplementasikan `io.Seeker` antarmuka, klien tidak akan dapat menghitung `ContentLength` parameter untuk permintaan tersebut. Parameter harus disediakan oleh aplikasi. Permintaan akan gagal jika `ContentLength` parameter tidak disediakan.   
 Gunakan SDK [Manajer Unggahan Amazon S3](#s3-upload-manager) untuk upload yang tidak dapat dicari dan tidak memiliki panjang yang diketahui. 