一、Cloudflare R2 基础使用流程
1. 注册与服务开通详解
账号注册步骤:
- 访问 Cloudflare 官网 点击 "Sign Up"
- 在控制台左侧菜单找到 "R2 Storage"
服务激活要点:
- 地域选择建议:初次使用推荐
亚太区域,网络延迟较低 - 存储类默认选择:Standard Storage(免费计划仅支持该类型)
2. 存储桶(Bucket)创建全流程
核心配置项说明:
| 配置项 | 推荐设置 | 说明 |
|---|---|---|
| 存储桶名称 | 全局唯一小写字母组合 | 例:my-photo-bucket-2025,后续可作为自定义域名前缀 |
| 区域选择 | 离用户最近的 Cloudflare 节点 | 自动 即可 |
| 存储类设置 | 保持 Standard 不变 |
公共访问配置实操:
- 进入存储桶详情页,点击 "设置" 标签
2. 开启 "公共开发URL" 开关
- 上传测试文件后,在文件详情页获取形如
https://<bucket>.r2.cloudflarestorage.com/<path>的 URL
4. 自定义域名绑定高级设置
配置优势:
- 统一资源访问域名(如
https://img.example.com) - 利用 Cloudflare CDN 节点加速全球访问
- 支持 HTTPS 免费证书自动部署
前提条件
域名需在cloudfare托管(修改原域名购买网站的dns解析服务器)
操作步骤
- 在存储桶设置中选择 "自定义域名"
- 输入已托管在 Cloudflare 的域名(如
img.example.com)
4. 系统自动生成 CNAME 记录,确认 DNS 解析生效
二、API令牌的获取
注意:该页面的密钥只展示一次,关闭后无法再次查看
三、桌面端工具 PicGo
1. PicGo 安装与环境配置
稳定版安装包获取:
- Windows:64 位安装包
- macOS:DMG 安装包
- Linux:AppImage 包
关键插件安装:
- 打开 PicGo 设置中的 "插件设置",搜索
s3并安装picgo-plugin-s3插件
2.重启 PicGo 使插件生效,根据提示填写
2. R2 存储配置参数详解
配置表单填写指南:
| 字段名称 | 取值示例 | 数据来源说明 |
|---|---|---|
| 存储区域 | auto | 保持默认即可,自动适配 Cloudflare 区域 |
| 存储桶名称 | my-photo-bucket-2025 | 填写已创建的 R2 存储桶名称 |
| 访问密钥 ID | ABCDEFGHIJKLMNOPQRSTUVW | 从 Cloudflare 控制台 API 令牌页面获取 |
| 密钥访问密钥 | 1234567890abcdefghijklmnopqrstuvw | 同上,注意该值仅显示一次需妥善保存 |
| endpoint | https:// <accountID>.r2.cloudflarestorage.com | 格式固定,accountID 可在存储桶概览页获取 |
| CDN 域名 | img.example.com | 填写已绑定的自定义域名 |
3. 高效上传操作技巧
支持的上传方式:
- 拖拽上传:直接拖放图片到 PicGo 窗口
- 剪贴板上传:截图后按
Ctrl+Shift+P快捷上传 - 批量上传:选择多个文件一次性导入
- 插件联动:与 Markdown 编辑器集成,自动替换本地图片链接
三、Spring Boot 后端集成完整方案
1. 依赖管理与版本说明
Maven 依赖配置:
<dependencies>
<!-- AWS SDK for S3 (兼容Cloudflare R2) -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.29.52</version>
</dependency>
<!-- EC2依赖用于区域自动识别 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>ec2</artifactId>
<version>2.29.52</version>
</dependency>
<!-- HTTP客户端用于底层请求 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
</dependencies>
版本选择注意事项:
- 2.30.0 + 版本需额外配置签名算法
2. 配置文件与常量管理
application.yml 完整配置:
cloud:
aws:
s3:
endpoint: https://abc123.r2.cloudflarestorage.com # 替换为实际accountID
bucket-name: my-spring-boot-bucket # 替换为实际存储桶名
cdn-domain: img.example.com # 替换为自定义域名
region: auto # 自动识别区域
credentials:
access-key: YOUR_ACCESS_KEY # 替换为API访问密钥
secret-key: YOUR_SECRET_KEY # 替换为API秘密密钥
3. 核心代码实现
config代码
@Component
public class R2FileUtils implements InitializingBean {
public static String END_POINT;
public static String REGION;
public static String BUCKET_NAME;
public static String CDN_DOMAIN;
public static String ACCESS_KEY;
public static String SECRET_KEY;
@Value("${cloud.aws.s3.endpoint}")
private String endpoint;
@Value("${cloud.aws.s3.region}")
private String region;
@Value("${cloud.aws.s3.bucket-name}")
private String bucketName;
@Value("${cloud.aws.s3.cdn-domain}")
private String cdnDomain;
@Value("${cloud.aws.s3.credentials.access-key}")
private String accessKey;
@Value("${cloud.aws.s3.credentials.secret-key}")
private String secretKey;
@Override
public void afterPropertiesSet() throws Exception {
END_POINT = this.endpoint;
REGION = this.region;
BUCKET_NAME = this.bucketName;
CDN_DOMAIN = this.cdnDomain;
ACCESS_KEY = this.accessKey;
SECRET_KEY = this.secretKey;
}
}
controller代码
@RestController
@RequestMapping("/api/file")
@Api(tags = "文件上传接口")
public class FileUploadController {
@Resource
private FileUploadService fileUploadService;
@PostMapping("/r2/upload")
@ApiOperation("Cloudflare R2文件上传")
@ApiImplicitParam(name = "file", value = "上传文件", required = true,
dataType = "MultipartFile")
public CommonResult<String> uploadToR2(@RequestPart("file") MultipartFile file) {
// 前置校验
if (file.isEmpty()) {
return CommonResult.error(ErrorCode.FILE_EMPTY);
}
// 调用服务层
String url = fileUploadService.uploadToR2(file);
return CommonResult.success(url, "上传成功");
}
}
serviceImpl核心代码
@Service
public class FileUploadServiceImpl implements FileUploadService {
@Override
public String uploadToR2(MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
// 构建S3客户端
S3Client s3Client = S3Client.builder()
.endpointOverride(URI.create(R2Config.END_POINT))
.credentialsProvider(() -> AwsBasicCredentials.create(
R2Config.ACCESS_KEY, R2Config.SECRET_KEY))
.region(Region.of(R2Config.REGION))
.build();
// 生成唯一文件名(含日期路径)
String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
String originalFilename = file.getOriginalFilename();
String fileExt = originalFilename.substring(originalFilename.lastIndexOf("."));
String objectKey = datePath + "/" + UUID.randomUUID() + fileExt;
// 构建上传请求
PutObjectRequest putRequest = PutObjectRequest.builder()
.bucket(R2Config.BUCKET_NAME)
.key(objectKey)
.contentType(file.getContentType())
.build();
// 执行上传
s3Client.putObject(putRequest,
RequestBody.fromInputStream(inputStream, file.getSize()));
// 生成可访问URL(含CDN域名)
return R2Config.CDN_DOMAIN + "/" + objectKey;
} catch (IOException | S3Exception e) {
log.error("R2文件上传失败: {}", e.getMessage(), e);
throw new FileUploadException("文件上传失败,请稍后再试");
}
}
}
接口测试
除此之外还可以限制文件大小,格式,设置定期删除等功能,示例中不再赘述。
五、参考资源
-
官方核心文档:
-
社区最佳实践: