Golang如何从S3存储桶中读取文件数据

Golang如何从S3存储桶中读取文件数据 在 Go 语言中,能否直接从 S3 文件读取数据?而不是先下载文件再从本地目录读取?另外,如果从文件读取数据,处理完成后如何将该文件移动到另一个存储桶?

2 回复

更多关于Golang如何从S3存储桶中读取文件数据的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在 Go 中可以直接从 S3 读取文件数据而无需完整下载到本地。使用 AWS SDK for Go (v2) 的 s3.GetObject 方法可以流式读取数据。以下是具体实现:

package main

import (
    "context"
    "fmt"
    "io"
    "log"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

func readFromS3(bucket, key string) ([]byte, error) {
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        return nil, fmt.Errorf("加载配置失败: %v", err)
    }

    client := s3.NewFromConfig(cfg)
    
    output, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(key),
    })
    if err != nil {
        return nil, fmt.Errorf("获取对象失败: %v", err)
    }
    defer output.Body.Close()

    return io.ReadAll(output.Body)
}

func main() {
    data, err := readFromS3("my-bucket", "path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("文件大小: %d 字节\n", len(data))
}

对于移动文件到另一个存储桶,可以使用 s3.CopyObject 复制后删除原文件:

func moveBetweenBuckets(srcBucket, srcKey, dstBucket, dstKey string) error {
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        return fmt.Errorf("加载配置失败: %v", err)
    }

    client := s3.NewFromConfig(cfg)
    
    // 复制到目标存储桶
    _, err = client.CopyObject(context.TODO(), &s3.CopyObjectInput{
        Bucket:     aws.String(dstBucket),
        Key:        aws.String(dstKey),
        CopySource: aws.String(fmt.Sprintf("%s/%s", srcBucket, srcKey)),
    })
    if err != nil {
        return fmt.Errorf("复制对象失败: %v", err)
    }

    // 删除源文件
    _, err = client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{
        Bucket: aws.String(srcBucket),
        Key:    aws.String(srcKey),
    })
    if err != nil {
        return fmt.Errorf("删除源对象失败: %v", err)
    }

    return nil
}

func main() {
    // 读取数据
    data, err := readFromS3("source-bucket", "data.csv")
    if err != nil {
        log.Fatal(err)
    }
    
    // 处理数据
    processedData := processData(data)
    
    // 移动文件
    err = moveBetweenBuckets("source-bucket", "data.csv", 
                            "destination-bucket", "processed/data.csv")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Println("文件移动完成")
}

func processData(data []byte) []byte {
    // 数据处理逻辑
    return data
}

对于大文件处理,建议使用流式处理避免内存溢出:

func processLargeFile(bucket, key string) error {
    cfg, err := config.LoadDefaultConfig(context.TODO())
    if err != nil {
        return err
    }

    client := s3.NewFromConfig(cfg)
    
    output, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(key),
    })
    if err != nil {
        return err
    }
    defer output.Body.Close()

    // 使用 bufio.Scanner 逐行处理
    scanner := bufio.NewScanner(output.Body)
    for scanner.Scan() {
        line := scanner.Text()
        // 处理每一行数据
        fmt.Println(line)
    }
    
    return scanner.Err()
}

这些方法可以直接操作 S3 对象而无需本地存储中间文件。

回到顶部