使用 Go 和 AWS SDK v2 实现在不同数据源之间复制目录
package main
import (
"context"
"fmt"
"log"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
type S3Config struct {
AccessKey string
SecretKey string
Endpoint string
Region string
}
func createS3Client(cfg S3Config) *s3.Client {
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
URL: cfg.Endpoint,
}, nil
})
awsCfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(cfg.AccessKey, cfg.SecretKey, "")),
config.WithEndpointResolverWithOptions(customResolver),
config.WithRegion(cfg.Region),
)
if err != nil {
log.Fatal(err)
}
return s3.NewFromConfig(awsCfg)
}
func copyDirectory(sourceClient *s3.Client, destClient *s3.Client, sourceBucket, destBucket, sourcePrefix, destPrefix string) error {
// 列出源目录中的所有对象
paginator := s3.NewListObjectsV2Paginator(sourceClient, &s3.ListObjectsV2Input{
Bucket: aws.String(sourceBucket),
Prefix: aws.String(sourcePrefix),
})
for paginator.HasMorePages() {
page, err := paginator.NextPage(context.TODO())
if err != nil {
return fmt.Errorf("failed to list objects: %v", err)
}
for _, obj := range page.Contents {
// 构建目标对象的键
sourceKey := *obj.Key
destKey := destPrefix + sourceKey[len(sourcePrefix):]
// 创建复制源的格式化字符串
copySource := fmt.Sprintf("%s/%s", sourceBucket, sourceKey)
// 复制对象
_, err := destClient.CopyObject(context.TODO(), &s3.CopyObjectInput{
Bucket: aws.String(destBucket),
CopySource: aws.String(copySource),
Key: aws.String(destKey),
})
if err != nil {
return fmt.Errorf("failed to copy object %s: %v", sourceKey, err)
}
fmt.Printf("Copied: %s -> %s\n", sourceKey, destKey)
}
}
return nil
}
func main() {
// 配置源数据源
sourceConfig := S3Config{
AccessKey: "source_access_key",
SecretKey: "source_secret_key",
Endpoint: "source_endpoint",
Region: "source_region", // 例如 "us-east-1"
}
// 配置目标数据源
destConfig := S3Config{
AccessKey: "dest_access_key",
SecretKey: "dest_secret_key",
Endpoint: "dest_endpoint",
Region: "dest_region", // 例如 "us-east-1"
}
// 创建源和目标 S3 客户端
sourceClient := createS3Client(sourceConfig)
destClient := createS3Client(destConfig)
// 设置源和目标桶及目录
sourceBucket := "source-bucket"
destBucket := "dest-bucket"
sourcePrefix := "test/"
destPrefix := "test/"
// 执行目录复制
err := copyDirectory(sourceClient, destClient, sourceBucket, destBucket, sourcePrefix, destPrefix)
if err != nil {
log.Fatal(err)
}
fmt.Println("Directory copy completed successfully")
}
这个程序的主要功能:
-
定义了
S3Config
结构体来存储 S3 配置信息(AK、SK、Endpoint 等) -
createS3Client
函数用于创建 S3 客户端,支持自定义 endpoint -
copyDirectory
函数实现目录复制功能:- 列出源目录中的所有对象
- 为每个对象构建目标路径
- 使用 CopyObject API 复制每个对象
-
在 main 函数中:
- 配置源和目标数据源的信息
- 创建相应的 S3 客户端
- 指定源和目标桶及目录
- 执行复制操作
使用说明:
- 首先安装必要的依赖:
go get github.com/aws/aws-sdk-go-v2
go get github.com/aws/aws-sdk-go-v2/config
go get github.com/aws/aws-sdk-go-v2/credentials
go get github.com/aws/aws-sdk-go-v2/service/s3
-
在使用时,需要替换以下配置:
- source_access_key:源数据源的 AccessKey
- source_secret_key:源数据源的 SecretKey
- source_endpoint:源数据源的 Endpoint
- dest_access_key:目标数据源的 AccessKey
- dest_secret_key:目标数据源的 SecretKey
- dest_endpoint:目标数据源的 Endpoint
- source-bucket:源桶名
- dest-bucket:目标桶名
-
程序会将源数据源中指定目录下的所有文件复制到目标数据源的指定目录中,保持相同的目录结构。
注意事项:
- 确保两个数据源的认证信息(AK/SK)具有足够的权限
- 确保网络连接正常
- 对于大文件或大量文件,可能需要考虑添加错误重试机制
- 可以根据需要添加进度显示、并发控制等功能