"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"
// Load environment variables
accountID := os.Getenv("R2_ACCOUNT_ID")
accessKeyID := os.Getenv("R2_ACCESS_KEY_ID")
secretAccessKey := os.Getenv("R2_SECRET_ACCESS_KEY")
bucketName := os.Getenv("R2_BUCKET_NAME")
// Hash the secret access key
hasher.Write([]byte(secretAccessKey))
hashedSecretKey := hex.EncodeToString(hasher.Sum(nil))
// Configure the S3 client for Cloudflare R2
r2Resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
URL: fmt.Sprintf("https://%s.r2.cloudflarestorage.com", accountID),
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithEndpointResolverWithOptions(r2Resolver),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKeyID, hashedSecretKey, "")),
config.WithRegion("auto"), // Cloudflare R2 doesn't use regions, but this is required by the SDK
log.Fatalf("Unable to load SDK config, %v", err)
client := s3.NewFromConfig(cfg)
// Specify the object key
objectKey := "2024/08/02/ingested_0001.parquet"
output, err := client.GetObject(context.TODO(), &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
log.Fatalf("Unable to fetch object, %v", err)
defer output.Body.Close()
fmt.Println("Successfully fetched the object")
// Process the object content as needed
// For example, to save the file:
// file, err := os.Create("ingested_0001.parquet")
// log.Fatalf("Unable to create file, %v", err)
// _, err = io.Copy(file, output.Body)
// log.Fatalf("Unable to write file, %v", err)
// Or to read the content:
content, err := io.ReadAll(output.Body)
log.Fatalf("Unable to read object content, %v", err)
fmt.Printf("Object content length: %d bytes\n", len(content))