后端低代码AI 应用人工智能AI Agent认证鉴权RAG【免费下载链接】erupt 通用数据管理框架VORM 对象视图模型注解驱动低代码开发项目地址https://gitcode.com/erupts/erupt点击查看免费下载本指南基于 Erupt 仓库中的erupt-data-s3模块讲解如何把 AWS S3、MinIO、阿里云 OSS、腾讯云 COS、Cloudflare R2 等 S3 兼容对象存储接入 Erupt 框架既可以把一个存储桶当作Erupt模型的数据源获得带权限、可搜索、可审计、支持标准删除流程的管理视图也可以用内置的S3AttachmentProxy把 Erupt 的附件上传Edit(type ATTACHMENT)、富文本图片等从本地磁盘迁到对象存储。读完本文你将掌握EruptS3注解与erupt.s3.*配置的全部参数、各厂商的端点/寻址方式差异以及底层的实现原理与常见坑位。模块定位两件事一个依赖erupt-data-s3pom.xml基于 AWS SDK v2版本由父工程统一管理提供两大能力S3 数据源将存储桶或桶内某个前缀下的对象映射为 Erupt 模型的行记录通过EruptS3注解声明连接信息配合EruptS3DataService.DATA_PROCESSOR注册数据处理器即可获得 Erupt 标准的列表、详情、删除管理界面。S3 附件代理S3AttachmentProxy实现了 Erupt 的 AttachmentProxy 接口把每次附件上传写入桶而不是本地磁盘。需要特别说明的是该模块只支持读取与删除Read delete only。通过管理表单直接上传原始对象内容并不合适请使用 S3 SDK 或应用自身的上传流程来写入对象。从源码看这一点体现在 EruptS3DataService 的addData/editData中——两者都会抛出 对象内容不可编辑 的异常属于刻意为之的只读设计。EruptS3 注解把模型绑定到一个桶EruptS3是模块的核心入口定义于 EruptS3.java目标类型为类ElementType.TYPE必须与EruptDataProcessor(EruptS3DataService.DATA_PROCESSOR)同时使用。在配置的前缀prefix下每一个对象就是一行数据模型的主键列对应对象键key。属性默认值说明bucket—必填要列出的桶prefix键前缀过滤器为空则列出整个桶regionus-east-1区域名——AWS 必填对非 AWS 厂商配合endpoint使用任意非空值即可endpoint端点 URL为空则使用该region对应的 AWS 默认端点accessKeyAccess key为空则走默认凭证链环境变量 /~/.aws/credentials/ 实例角色secretKeySecret key仅当accessKey已设置时才被读取pathStylefalse强制路径风格寻址https://endpoint/bucket/key——MinIO 和较老的 OSS 网关必须开启pageSize1000单次 List 调用最多返回的对象数maxObjects5000跨所有分页的硬性总上限防止超大桶上的失控列举模型可用字段EruptS3数据源可映射以下字段字段名必须保持固定尤其是key它是主键字段类型填充时机keyStringlist findsizeLonglist findlastModifiedDatelist findetagStringlist findstorageClassStringlist findcontentTypeString仅 findmetadataMapString,String仅 find来自x-amz-meta-*请求头从 toRow 方法 可以看到列表数据来自ListObjectsV2响应中的S3Object包含 key、size、lastModified、etag、storageClass而contentType与metadata只在findDataById中通过HeadObject响应补齐。示例一AWS S3把生产环境上传桶prod-uploads的reports/前缀做成一个可搜索、可审计的管理视图Getter Setter Erupt(name S3 Objects, primaryKeyCol key) EruptS3(bucket prod-uploads, prefix reports/, region us-east-1) EruptDataProcessor(EruptS3DataService.DATA_PROCESSOR) public class S3ProductionUpload { EruptField(views View(title Key)) private String key; EruptField(views View(title Size (bytes))) private Long size; EruptField(views View(title Last Modified)) private Date lastModified; EruptField(views View(title ETag)) private String etag; EruptField(views View(title Storage Class)) private String storageClass; }示例二MinIO / 自托管自建 MinIO 需要显式指定endpoint并开启pathStyleEruptS3( bucket erupt-uploads, endpoint http://minio.internal:9000, region us-east-1, accessKey AKIAxxx, secretKey xxx, pathStyle true )示例三其他厂商端点速查厂商endpointpathStyle阿里云 OSShttps://oss-cn-hangzhou.aliyuncs.comfalse腾讯云 COShttps://cos.ap-guangzhou.myqcloud.comfalseCloudflare R2https://account.r2.cloudflarestorage.comtrueBackblaze B2 (S3 API)https://s3.region.backblazeb2.comtrueendpoint是服务service主机不是桶主机。如果你把控制台里复制的桶地址如https://mybucket.s3.cn-south-1.qiniucs.com粘贴进来模块会识别并去掉前导的mybucket.标签。这一逻辑实现在 S3ClientFactory.endpoint虚拟主机风格下若端点主机以bucket.开头会通过正则将其剥离为服务主机避免 SDK 再次把桶名前置后请求落到不存在的桶上而路径风格下端点保持不变桶本就在路径里。测试用例 S3AttachmentProxyTest#bucketHostEndpointIsReducedToServiceHost 还覆盖了主机名恰好以桶名开头但不是桶标签如erupt-uploadsx.example.com不误判的边界情况。底层操作与数据服务原理EruptS3DataService 继承EruptBeanDataServiceMapString, Object在静态代码块中通过DataProcessorManager.register(DATA_PROCESSOR, EruptS3DataService.class)注册为名为S3的数据处理器对应以下操作List列表ListObjectsV2 continuation-token 分页总条数受maxObjects硬性约束。实现细节data 方法每次请求maxKeys取pageSize与剩余额度两者较小值逐条累积S3Object一旦remaining归零立即返回避免超大桶的失控列举响应isTruncated为 true 时用nextContinuationToken继续翻页。Find by id详情HeadObject额外填充contentType与metadata字段当抛NoSuchKeyException时返回nullfindDataById 方法。Delete删除按主键key调用DeleteObject主键为空时抛出 对象键不能为空 的多语言异常deleteData 方法。Add / Edit不支持调用即抛异常。值得注意的实现细节客户端缓存S3Client按endpoint|region|accessKey|pathStyle四元组缓存在ConcurrentHashMap中client 方法多个模型即使桶级配置不同只要连接参数一致就复用底层 HTTP 客户端PreDestroy时统一close。凭证链由 S3ClientFactory.build 统一构建——accessKey为空时使用DefaultCredentialsProvider环境变量 /~/.aws/credentials/ 实例角色设置时才使用StaticCredentialsProvider。错误包装所有 S3 异常统一包装为EruptWebApiRuntimeException并带上 AWS 错误详情或异常消息wrap 方法。错误文案如s3.operation_failed、s3.read_only_edit、s3.bucket_missing、s3.primary_key_missing在 erupt-s3.i18n.csv 中提供了中、英、日、韩、俄、西、法、德、葡、印尼、阿拉伯等多语言翻译可通过 Erupt 的 i18n 机制随界面语言切换。附件上传S3AttachmentProxy 接入步骤S3AttachmentProxy源码是一个现成的AttachmentProxy实现Erupt 每次附件上传Edit(type ATTACHMENT)、富文本图片等都会通过它写入桶而非本地磁盘。启用分两步第一步在 Spring Boot 启动类上声明使用该代理。EruptAttachmentUpload定义于 erupt-core 的注解包必须标注在启动类上其value指定AttachmentProxy实现类SpringBootApplication EruptScan EruptAttachmentUpload(S3AttachmentProxy.class) public class DemoApplication { ... }第二步在application.yml中配置erupt.s3.*erupt: s3: bucket: erupt-uploads region: ap-southeast-1 endpoint: http://minio.internal:9000 # 省略则为 AWS path-style: true # MinIO / 自托管 prefix: erupt/ # 可选键前缀 access-key: ${S3_ACCESS_KEY} secret-key: ${S3_SECRET_KEY} domain: https://cdn.example.com # 可选公网基础 URLCDN为空时根据 endpoint bucket 推导 local-save: false # true 时同时在 erupt.upload-path 下保留一份副本对应属性绑定类为 EruptS3PropertiesConfigurationProperties(prefix erupt.s3)由 EruptS3AutoConfiguration 通过EnableConfigurationProperties注册属性默认值说明erupt.s3.bucket—必填接收上传的桶erupt.s3.prefix桶内的键前缀erupt.s3.regionus-east-1区域名erupt.s3.endpoint端点 URL为空表示 AWSerupt.s3.access-key/secret-key静态凭证为空走默认凭证链erupt.s3.path-stylefalse路径风格寻址erupt.s3.domain浏览器加载文件的公网基础 URL为空时按https://bucket.s3.region.amazonaws.comAWS、endpoint/bucket路径风格或scheme://bucket.endpoint-host虚拟主机风格推导erupt.s3.local-savefalse同时在本地服务器保留一份文件上传与访问路径是如何拼接的Erupt 生成的路径/yyyy-MM-dd/xxxx.ext会成为prefix下的对象键而数据库里存储的值仍然是这个路径本身——后续即使切换存储方案也不需要改写历史数据。从 S3AttachmentProxy 源码可以看到三条关键逻辑对象键keykey(path)把配置的prefix去首尾斜杠后拼在去掉前导斜杠的路径前面例如prefixerupt/、路径/2026-09-24/abc.png→ 对象键erupt/2026-09-24/abc.png。Content-TypeupLoad用URLConnection.guessContentTypeFromName(path)根据扩展名猜测 Content-Type 并写入PutObjectRequest保证图片等文件在浏览器中以内联方式渲染而非被强制下载由于MultipartFile流不暴露长度SDK 需要一次性读取全部字节RequestBody.fromBytes。公网 URLfileDomainfileDomain()优先使用domain为空时按 endpoint / region 与 bucket 推导——AWS 为虚拟主机 URL路径风格为endpoint/bucket自定义端点虚拟主机风格为scheme://bucket.host[:port]最后再拼上prefix。上传入口在 erupt-core 的 EruptFileService拿到EruptAttachmentUpload指定的代理后调用attachmentProxy.upLoad(file.getInputStream(), path)返回的路径写入数据库。前端展示时EruptFileController 用fileDomain() path拼出可访问的 URL未配置代理时才回退到 Erupt 自身的附件接口。EruptUtil.attachmentUrl 还会校验拼接后的 URL 与域名在 scheme、host、port 上完全一致防止以或.开头的存储路径被解析成 userinfo 或主机名的一部分而把请求发送到别处。测试用例 S3AttachmentProxyTest 完整验证了上述推导逻辑AWS 虚拟主机风格、MinIO 路径风格带前缀、自定义端点虚拟主机风格、桶主机端点还原为服务主机以及显式domain覆盖并携带前缀五种场景均保证fileDomain() path与key(path)写入的对象可正确解析。公网可读要求桶或桶前的 CDN必须允许公开读或者domain指向一个允许公开读的地址否则浏览器无法加载附件。常见坑位Gotchaskey字段不可改名它是 S3 对象键原样映射同时作为模型主键列primaryKeyCol key。超大桶的结果截断当前缀下对象超过 5000 个时列表结果会被maxObjects硬性截断。应对方式用prefix收窄范围或显式调大maxObjects。注意pageSize只控制单次 List 调用的页大小翻页会一直继续到maxObjects为止。metadata只在详情页有值它来自 HEAD 请求findDataById列表视图不会填充——如果把metadata放进列表列渲染出来是空的。引入方式在模块pom.xml中按坐标引入版本由父工程统一管理S3 SDK 通过software.amazon.awssdk:bom导入pom.xmldependency groupIdxyz.erupt/groupId artifactIderupt-data-s3/artifactId /dependency模块通过EruptS3AutoConfiguration实现 EruptModule 自动装配加入依赖后即可使用EruptS3注解与S3AttachmentProxy。综上erupt-data-s3用一组注解和一份配置把对象存储只读管理 附件上云两件高频需求压缩到了极少的代码量内。对需要审计、检索云上对象或想摆脱本地磁盘附件的 Erupt 应用它是一条现成的落地方案。赞分享后端低代码AI 应用人工智能AI Agent认证鉴权RAG【免费下载链接】erupt 通用数据管理框架VORM 对象视图模型注解驱动低代码开发项目地址https://gitcode.com/erupts/erupt点击查看免费下载相关推荐Rust对象存储S3兼容接口与文件管理Rust对象存储S3兼容接口与文件管理 你是否在寻找一种既能保证高性能又能确保数据安全的对象存储解决方案Rust作为一种注重安全和效率的系统级编程语言为构编程语言编译器语言运行时标准库Supabase S3 Wrapper 完全指南用只读外表把 S3 对象存储变成 Postgres 可查询的表Supabase S3 Wrapper 完全指南用只读外表把 S3 对象存储变成 Postgres 可查询的表 本文基于 Supabase 仓库中 Studi后端前端数据库dokku对象存储MinIO/S3兼容存储dokku对象存储MinIO/S3兼容存储 你是否在为应用部署时的文件存储问题烦恼还在手动配置云存储服务吗本文将详细介绍如何使用dokku的存储插件实现与云原生DevOps后端上一篇OSS-Fuzz 全解析为开源软件构建持续模糊测试Fuzzing体系下一篇深入解析 Vercel React 最佳实践规则模板为 next-shadcn-dashboard-starter 编写高性能规则清单的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考