Cloudflare R2 为对象存储提供了一个相对 AWS S3 更具成本效益的替代方案,最大的优势是没有出站流量费用。在本教程中,我们将探讨如何使用 Go 语言通过 AWS SDK for Go v2 来上传文件到 Cloudflare R2,充分利用 R2 兼容 S3 的 API。
前置要求
在开始之前,请确保你具备:
- 系统中已安装 Go 语言环境
- 已启用 R2 功能的 Cloudflare 账户
- R2 的访问凭证(账户 ID、访问密钥 ID 和密钥)
- 基本的 Go 编程知识
项目设置
首先,创建一个新的 Go 项目并安装所需的 AWS SDK 包:
mkdir r2-upload
cd r2-upload
go mod init r2-upload
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
具体实现
以下是一个完整的示例,展示如何将文件上传到 Cloudflare R2:
package main
import (
"context"
"fmt"
"log"
"os"
"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"
)
func main() {
// R2 凭证
accountID := "your_account_id"
accessKeyID := "your_access_key_id"
accessKeySecret := "your_access_key_secret"
// 自定义 R2 端点解析器
r2Resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
URL: fmt.Sprintf("https://%s.r2.cloudflarestorage.com", accountID),
}, nil
})
// 配置 AWS SDK
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithEndpointResolverWithOptions(r2Resolver),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKeyID, accessKeySecret, "")),
config.WithRegion("auto"),
)
if err != nil {
log.Fatal(err)
}
// 创建 S3 客户端
client := s3.NewFromConfig(cfg)
// 打开要上传的文件
file, err := os.Open("example.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 上传文件
_, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String("your-bucket-name"),
Key: aws.String("example.txt"),
Body: file,
})
if err != nil {
log.Fatal(err)
}
log.Println("文件上传成功")
}
代码解析
让我们来分析代码的关键部分:
1. 配置设置
r2Resolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
URL: fmt.Sprintf("https://%s.r2.cloudflarestorage.com", accountID),
}, nil
})
这段代码创建了一个自定义端点解析器,指向你的 R2 存储桶的端点。URL 格式是 Cloudflare R2 特有的。
2. AWS SDK 配置
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithEndpointResolverWithOptions(r2Resolver),
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKeyID, accessKeySecret, "")),
config.WithRegion("auto"),
)
这里配置了 AWS SDK,包括你的 R2 凭证和自定义端点解析器。注意我们使用 "auto" 作为区域,因为 R2 不使用传统的 AWS 区域。
3. 文件上传
_, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String("your-bucket-name"),
Key: aws.String("example.txt"),
Body: file,
})
这段代码将文件上传到你的 R2 存储桶。Key
参数决定了文件在存储桶中的名称。
最佳实践和提示
-
错误处理:始终在每个步骤检查错误,特别是在文件操作和上传过程中。
-
文件管理:使用
defer file.Close()
确保文件在使用后正确关闭。 -
安全性:永远不要在代码中硬编码凭证。请使用环境变量或配置文件:
accountID := os.Getenv("R2_ACCOUNT_ID")
accessKeyID := os.Getenv("R2_ACCESS_KEY_ID")
accessKeySecret := os.Getenv("R2_ACCESS_KEY_SECRET")
- 内容类型:你可以指定上传文件的内容类型:
_, err = client.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String("your-bucket-name"),
Key: aws.String("example.txt"),
Body: file,
ContentType: aws.String("text/plain"),
})
常见问题和解决方案
- 连接问题
- 仔细检查你的账户 ID 和端点 URL
- 验证 R2 存储桶是否存在且配置正确
- 确保防火墙没有阻止连接
- 身份验证错误
- 验证访问密钥 ID 和密钥是否正确
- 检查 R2 令牌是否具有必要的权限
- 确保你的凭证没有过期
总结
使用 Go 与 Cloudflare R2 结合为应用程序提供了一个强大且经济的对象存储解决方案。AWS SDK 的 S3 兼容性使其实现变得简单直接,而 R2 的定价模型(特别是没有出站流量费用)使其成为许多用例的理想选择。
记住在生产代码中始终遵循安全最佳实践并正确处理错误。对于更高级的用法,你可能想要探索其他功能,如大文件的分片上传或实现重试逻辑以提高可靠性。