基于 Spring Boot WebFlux 构建的 S3 兼容 API 服务,提供对 MinIO/S3 存储的直接 S3 兼容端点访问,具备文件去重功能。
本项目是一个高性能的 S3 兼容代理服务,采用响应式编程模型,支持文件去重、多种数据库后端,并提供完整的 S3 API 兼容性。主要用于简化对象存储访问、减少存储空间占用(通过去重功能)、以及提供统一的 S3 接口。
- ✅ S3 兼容 API: 提供标准 S3 API 端点,无需代理路径前缀
- ✅ 文件去重: 基于内容寻址的存储系统,通过引用计数消除重复文件
- ✅ 文件操作: 支持上传、下载、删除文件,保留 content-type 头部信息
- ✅ 存储桶操作: 通过 HEAD 请求检查存储桶是否存在
- ✅ 二进制支持: 处理所有文件类型,包括二进制数据
- ✅ 响应式架构: 基于 Spring WebFlux 的非阻塞操作
- ✅ MinIO SDK 兼容: 与 MinIO SDK 和其他 S3 客户端兼容
- ✅ 多数据库支持: 支持 H2(开发/测试)和 MySQL(生产环境)
- ✅ 容器化支持: 提供 Docker 和 Docker Compose 部署方案
S3ProxyApplication: Spring Boot 主应用入口类,配置 JPA 仓库扫描S3CompatibleController: 核心控制器,处理所有 S3 兼容的 REST API 请求MinioConfig: MinIO 客户端配置类,管理与 MinIO 服务器的连接S3AuthenticationFilter: S3 认证过滤器,处理 AWS 签名验证
DeduplicationService: 文件去重服务,管理文件存储和引用计数HashService: 哈希计算服务,用于文件内容去重的哈希值计算MultipartUploadService: 多部分上传服务,处理大文件的分片上传
FileEntity: 文件实体类,存储文件元数据和哈希信息UserFileEntity: 用户文件关联实体类,管理用户与文件的映射关系DatabaseConfig: 数据库配置类,根据不同 profile 提供 H2 或 MySQL 配置
# 设置 MinIO 连接环境变量
export MINIO_ENDPOINT=http://localhost:9000
export MINIO_ACCESS_KEY=minioadmin
export MINIO_SECRET_KEY=minioadmin
# 启动应用(使用内嵌 H2 数据库)
mvn spring-boot:run# 设置 MinIO 环境变量
export MINIO_ENDPOINT=http://localhost:9000
export MINIO_ACCESS_KEY=minioadmin
export MINIO_SECRET_KEY=minioadmin
# 设置 MySQL 数据库配置
export SPRING_PROFILES_ACTIVE=mysql
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
export MYSQL_DB=s3proxy
export MYSQL_USERNAME=root
export MYSQL_PASSWORD=yourpassword
# 启动应用
mvn spring-boot:run# 构建包含所有依赖的 fat JAR(包含 H2 和 MySQL 驱动)
mvn clean package -DskipTests
# 验证构建结果
ls -la target/s3-proxy-java-0.1.0.jar# 设置环境变量
export MINIO_ENDPOINT=http://localhost:9000
export MINIO_ACCESS_KEY=minioadmin
export MINIO_SECRET_KEY=minioadmin
# 启动应用(默认使用 H2)
java -jar target/s3-proxy-java-0.1.0.jar
# 或者明确指定 H2 profile
SPRING_PROFILES_ACTIVE=h2 java -jar target/s3-proxy-java-0.1.0.jar# 方式一:通过环境变量
SPRING_PROFILES_ACTIVE=mysql \
MYSQL_HOST=localhost \
MYSQL_PORT=3306 \
MYSQL_DB=s3proxy \
MYSQL_USERNAME=root \
MYSQL_PASSWORD=yourpassword \
MINIO_ENDPOINT=http://localhost:9000 \
MINIO_ACCESS_KEY=minioadmin \
MINIO_SECRET_KEY=minioadmin \
java -jar target/s3-proxy-java-0.1.0.jar
# 方式二:通过 JVM 参数
java -jar target/s3-proxy-java-0.1.0.jar \
--spring.profiles.active=mysql \
--spring.datasource.url=jdbc:mysql://localhost:3306/s3proxy \
--spring.datasource.username=root \
--spring.datasource.password=yourpassword# 使用 H2 数据库的快速演示
./demo.sh
# 使用 MySQL 数据库的快速演示
./mysql-demo.sh# 构建镜像
docker build -t s3-proxy-java:latest .
# 查看镜像信息
docker images s3-proxy-java# 基本运行(使用默认 H2 数据库)
docker run -d \
--name s3-proxy \
-p 8080:8080 \
-e MINIO_ENDPOINT=http://host.docker.internal:9000 \
-e MINIO_ACCESS_KEY=minioadmin \
-e MINIO_SECRET_KEY=minioadmin \
s3-proxy-java:latest
# 查看日志
docker logs -f s3-proxy# 使用 MySQL 数据库运行
docker run -d \
--name s3-proxy-mysql \
-p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=mysql \
-e MYSQL_HOST=host.docker.internal \
-e MYSQL_PORT=3306 \
-e MYSQL_DB=s3proxy \
-e MYSQL_USERNAME=root \
-e MYSQL_PASSWORD=yourpassword \
-e MINIO_ENDPOINT=http://host.docker.internal:9000 \
-e MINIO_ACCESS_KEY=minioadmin \
-e MINIO_SECRET_KEY=minioadmin \
s3-proxy-java:latest项目提供了完整的 Docker Compose 配置,包含 S3 Proxy 应用、MinIO 服务和 MySQL 数据库。
# 启动 S3 Proxy 和 MinIO 服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f s3-proxy# 启动包含 MySQL 的完整环境
docker-compose --profile mysql up -d
# 查看所有服务状态
docker-compose --profile mysql ps
# 查看特定服务日志
docker-compose logs -f s3-proxy-mysql启动后,可以通过以下地址访问各个服务:
- S3 Proxy API: http://localhost:8080
- S3 Proxy API (MySQL): http://localhost:8081 (仅在使用 MySQL profile 时)
- MinIO 控制台: http://localhost:9001 (账号: minioadmin/minioadmin)
- MinIO API: http://localhost:9000
- MySQL: localhost:3306 (仅在使用 MySQL profile 时)
# 停止服务
docker-compose down
# 停止服务并删除数据卷
docker-compose down -v
# 停止 MySQL 环境
docker-compose --profile mysql down| 环境变量 | 默认值 | 说明 |
|---|---|---|
SPRING_PROFILES_ACTIVE |
h2 |
数据库配置文件 (h2/mysql) |
MINIO_ENDPOINT |
http://localhost:9000 |
MinIO 服务端点 |
MINIO_ACCESS_KEY |
minioadmin |
MinIO 访问密钥 |
MINIO_SECRET_KEY |
minioadmin |
MinIO 秘密密钥 |
MINIO_DEDUPE_BUCKET |
dedupe-storage |
去重存储桶名称 |
S3_AUTH_ENABLED |
true |
是否启用 S3 认证 |
MYSQL_HOST |
localhost |
MySQL 主机地址 |
MYSQL_PORT |
3306 |
MySQL 端口 |
MYSQL_DB |
s3proxy |
MySQL 数据库名 |
MYSQL_USERNAME |
root |
MySQL 用户名 |
MYSQL_PASSWORD |
(空) | MySQL 密码 |
JAVA_OPTS |
-Xms512m -Xmx1024m |
JVM 参数 |
服务提供标准的 S3 兼容端点:
| 方法 | 端点 | 描述 |
|---|---|---|
| PUT | /{bucket}/{key} |
上传文件到指定存储桶和键 |
| GET | /{bucket}/{key} |
从存储桶下载文件 |
| DELETE | /{bucket}/{key} |
从存储桶删除文件 |
| HEAD | /{bucket} |
检查存储桶是否存在 |
| HEAD | /{bucket}/{key} |
获取对象元数据 |
| GET | /{bucket}?list-type=2 |
列出存储桶中的对象 |
# 上传文件
curl -X PUT \
--data-binary @example.txt \
"http://localhost:8080/mybucket/folder/example.txt"
# 上传二进制文件
curl -X PUT \
--data-binary @image.jpg \
-H "Content-Type: image/jpeg" \
"http://localhost:8080/mybucket/images/image.jpg"# 下载文件
curl -L "http://localhost:8080/mybucket/folder/example.txt" -o downloaded.txt
# 获取文件元数据
curl -I "http://localhost:8080/mybucket/folder/example.txt"# 删除文件
curl -X DELETE "http://localhost:8080/mybucket/folder/example.txt"# 检查存储桶是否存在
curl -I "http://localhost:8080/mybucket"
# 列出存储桶对象
curl "http://localhost:8080/mybucket?list-type=2"
# 列出指定前缀的对象
curl "http://localhost:8080/mybucket?list-type=2&prefix=folder/"// Java MinIO SDK 示例
MinioClient client = MinioClient.builder()
.endpoint("http://localhost:8080") // 代理端点
.credentials("minioadmin", "minioadmin")
.build();
// 上传文件
client.putObject(
PutObjectArgs.builder()
.bucket("mybucket")
.object("myfile.txt")
.stream(inputStream, inputStream.available(), -1)
.build()
);
// 下载文件
GetObjectResponse response = client.getObject(
GetObjectArgs.builder()
.bucket("mybucket")
.object("myfile.txt")
.build()
);
// 列出对象
Iterable<Result<Item>> results = client.listObjects(
ListObjectsArgs.builder()
.bucket("mybucket")
.prefix("folder/")
.recursive(true)
.build()
);服务支持两种数据库后端:
- 用途: 适用于开发和测试环境
- 特点: 内嵌数据库,无需额外安装
- 数据存储:
./data/s3proxy.mv.db - 管理界面: http://localhost:8080/h2-console
# 使用 H2 数据库(默认配置)
mvn spring-boot:run
# 或明确指定
export SPRING_PROFILES_ACTIVE=h2
mvn spring-boot:run- 用途: 适用于生产环境
- 特点: 高性能、并发访问、优化索引
- 连接池: 支持 HikariCP 连接池优化
- 创建数据库
CREATE DATABASE s3proxy CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 可选:创建专用用户
CREATE USER 's3proxy'@'%' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON s3proxy.* TO 's3proxy'@'%';
FLUSH PRIVILEGES;- 配置环境变量
export SPRING_PROFILES_ACTIVE=mysql
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
export MYSQL_DB=s3proxy
export MYSQL_USERNAME=s3proxy
export MYSQL_PASSWORD=your_secure_password- 启动应用
mvn spring-boot:run应用会自动:
- 使用 Flyway 创建所需的表和优化索引
- 建立适当的外键关系
- 配置连接池以获得最佳性能
详细的 MySQL 配置信息请参考 MYSQL_CONFIGURATION.md。
本服务包含先进的文件去重功能,可自动消除重复文件:
- 内容寻址存储: 基于文件内容的 SHA-256 哈希值进行存储
- 引用计数: 多个用户可以引用同一个物理文件
- 自动清理: 当引用计数为零时自动删除物理文件
- 透明操作: 对用户完全透明,不影响正常的 S3 API 使用
详细的去重系统工作原理请参考 DEDUPLICATION.md。
# 运行所有测试
mvn test
# 跳过测试构建
mvn package -DskipTests- MinIO SDK 兼容性测试 (
MinioSdkCompatibilityDemoTest): 测试 MinIO SDK 集成 - MinIO SDK 单元测试 (
MinioSdkDirectProxyUnitTest): MinIO SDK 操作的单元测试 - 对象列表测试 (
ObjectListingTest): 对象列表功能测试 - 去重功能测试 (
DeduplicationIntegrationTest): 文件去重功能测试
- ✅ MinIO SDK 兼容性
- ✅ S3 兼容 API 端点
- ✅ 错误处理和边界情况
- ✅ 通过 Testcontainers 的真实 MinIO 集成
手动测试说明请参考 MANUAL_TESTING.md。
- 对于大对象优先使用零拷贝流;可替换为
DataBufferUtils.write(...)+PipedInputStream - 如果在 Nginx/Ingress 后面运行,请保留
Host头部以支持预签名 URL 流程 - 在公开暴露前添加认证(如 JWT)和速率限制
- 生产环境建议禁用 H2 控制台
- 使用强密码和密钥轮换
- 配置 HTTPS 和 SSL 数据库连接
- 定期备份数据库
- 监控数据库连接池状态
- 设置适当的 JVM 堆内存配置
- 配置日志轮换和存储
- 监控磁盘空间使用情况
-
连接 MinIO 失败
- 检查
MINIO_ENDPOINT环境变量是否正确 - 确认 MinIO 服务是否运行
- 验证访问密钥和秘密密钥
- 检查
-
数据库连接问题
- MySQL: 检查连接字符串和凭据
- H2: 确认数据目录的写入权限
-
Docker 网络问题
- 在 Docker 环境中使用
host.docker.internal访问宿主机服务 - 检查容器之间的网络连接
- 在 Docker 环境中使用
-
文件上传失败
- 检查 MinIO 存储桶是否存在并可访问
- 验证文件大小限制
- 查看应用日志了解具体错误信息
src/main/java/com/example/s3proxy/
├── S3ProxyApplication.java # 主应用入口
├── S3CompatibleController.java # S3 API 控制器
├── MinioConfig.java # MinIO 客户端配置
├── S3AuthenticationFilter.java # S3 认证过滤器
├── config/
│ └── DatabaseConfig.java # 数据库配置
├── entity/
│ ├── FileEntity.java # 文件实体
│ └── UserFileEntity.java # 用户文件关联实体
├── repository/
│ ├── FileRepository.java # 文件仓库接口
│ └── UserFileRepository.java # 用户文件仓库接口
├── service/
│ ├── DeduplicationService.java # 去重服务
│ ├── HashService.java # 哈希计算服务
│ └── MultipartUploadService.java # 多部分上传服务
└── util/ # 工具类
本项目采用 MIT 许可证 - 详情请参阅 LICENSE 文件。
欢迎提交 Issue 和 Pull Request 来改进这个项目。
本项目提供预构建的 Docker 镜像,可直接从 Docker Hub 获取:
# 拉取最新版本
docker pull chenmins/s3-proxy-java:latest
# 运行容器(必须提供环境变量)
docker run -d \
--name s3-proxy \
-p 8080:8080 \
-e MINIO_ENDPOINT=http://host.docker.internal:9000 \
-e MINIO_ACCESS_KEY=minioadmin \
-e MINIO_SECRET_KEY=minioadmin \
-e S3_AUTH_ENABLED=true \
chenmins/s3-proxy-java:latest注意:
- 请将
[DOCKER_USERNAME]替换为实际的 Docker Hub 用户名- 从安全考虑,敏感环境变量(如 MinIO 凭据)不再硬编码在镜像中,必须在运行时提供
- 建议在生产环境中使用更安全的方式管理敏感信息(如 Docker secrets 或 Kubernetes secrets)
详细的 Docker 发布和使用说明请参阅 Docker 发布流水线说明。