Skip to content

OSS文件存储

sz-admin 采用两个相互配合的模块处理文件存储,职责明确分离:

模块职责配置前缀
sz-common-oss厂商适配层。封装 MinIO / 阿里云 / 腾讯云 / 七牛云等底层 S3 SDK,负责 bucket 接入凭据管理。sz.oss.*
sz-common-resource业务抽象层。以「场景(sceneCode)」为核心,统一管理文件上传、路径规则、命名策略、访问模式和安全白名单。sz.resource.*

业务代码只需调用 ResourceService,不再直接依赖 OssClient;底层存储介质(本地/OSS)和访问方式(直链/预签名/代理)均通过 yml 配置切换,代码无需改动。

配置指南

新版配置分为两段写在 oss.yml 中:

yaml
sz:
  # oss 存储配置(厂商接入凭据)
  oss:
    # 支持 S3 协议的厂商: MINIO / ALIYUN / TENCENT / QINIU
    provider: MINIO
    endpoint: 192.168.100.176:9000
    accessKey: your-access-key
    secretKey: your-secret-key
    # 全局存储桶(场景未指定 bucket 时回退使用)
    bucketName: test
    domain: http://192.168.100.176:9000
    scheme: http

  # 场景资源配置(业务资源体系)
  resource:
    # 本地存储根目录(LOCAL 类型场景使用)
    root: ./data
    # 全局默认存储类型
    default-storage-type: LOCAL
    # 全局安全白名单
    security:
      allowed-exts: [jpg, jpeg, png, gif, bmp, webp, svg, ico, pdf, doc, docx, xls, xlsx, ppt, pptx, rtf, txt, csv, zip, rar, 7z, tar, gz, mp3, wav, ogg, mp4, mov, avi, wmv]
    max-size: 50MB

    scenes:

      # ========= 场景示例:账户头像 =========
      # 同一个 sceneCode 可注释切换三种模式,根据环境选择一种激活

      # 【模式一:本地存储 + Java 服务代理访问】(当前激活)
      - code: admin.user.logo
        type: LOCAL
        serve-mode: DIRECT
        base-url: http://127.0.0.1:9991/api/admin/resource/file/logo
        path: logo
        naming: ORIGINAL
        path-strategy: BIZ_DATE
        exts: [svg, png, jpg, jpeg, webp, gif]
        max-size: 3

      # 【模式二:OSS 私有桶 + 预签名 URL 访问】(注释状态)
      # - code: admin.user.logo
      #   type: OSS
      #   serve-mode: PRESIGNED
      #   bucket: client-logos
      #   base-url: http://192.168.100.176:9000/client-logos
      #   naming: ORIGINAL
      #   path-strategy: BIZ_DATE
      #   exts: [svg, png, jpg, jpeg, webp, gif]
      #   max-size: 3

      # 【模式三:OSS 公有桶 + 直链访问】(注释状态)
      # - code: admin.user.logo
      #   type: OSS
      #   serve-mode: DIRECT
      #   bucket: client-logos-public
      #   base-url: http://192.168.100.176:9000/client-logos-public
      #   naming: UUID
      #   path-strategy: BIZ_DATE
      #   exts: [svg, png, jpg, jpeg, webp, gif]
      #   max-size: 3

三种访问模式说明

模式typeserve-mode适用场景注意事项
本地 + Java 代理LOCALDIRECT开发/测试环境,无需 OSSbase-url 需配置为 Java 服务的资源代理地址或 Nginx 代理地址
OSS 私有 + 预签名OSSPRESIGNED生产环境,需要访问控制生成的 URL 有时效性(默认 3600 秒),适合合同、证件等敏感资源
OSS 公有 + 直链OSSDIRECT公开资源,无访问控制需求bucket 需设为公读,base-url 填写 OSS 公网访问地址

场景核心配置字段说明

字段说明可选值
code场景唯一标识(即前端 sceneCode),全局不可重复自定义字符串,建议 模块.用途 格式
type存储类型LOCAL(本地磁盘)/ OSS(对象存储)
pathLOCAL 类型必填,相对于 root 的存储子目录字符串路径
bucketOSS 类型必填,对应的 bucket 名称字符串
naming文件命名规则UUID(随机)/ ORIGINAL(原文件名,冲突时补时间戳)
path-strategy路径生成策略FLAT(扁平)/ DATE(按日期)/ BIZ_DATE(bizKey + 日期)
serve-mode访问模式DIRECT(直链)/ PRESIGNED(预签名,仅 OSS)/ TOKEN(token 鉴权)
base-urlDIRECT 模式必填,文件访问根地址URL 字符串
exts场景级文件扩展名白名单(覆盖全局 security.allowed-exts字符串列表
max-size场景级最大文件大小3(MB)或 3MB

TIP

完整配置说明及各云厂商(MinIO / 阿里云 / 腾讯云 / 七牛云)的详细接入指引,请阅读项目源码中的 sz-common-oss/docs/oss-provider-guide.md

使用场景

文件上传

统一通过 POST /resource/upload 接口上传,由前端传入 sceneCode 决定存储策略:

POST /resource/upload
Content-Type: multipart/form-data

sceneCode    = admin.user.logo    (必填,对应 yml 中的 scene code)
pathSegments = {userId}           (可选,BIZ_DATE 策略的业务路径分段,多段逗号分隔)
file         = <文件>

上传成功后的返回结果示例:

json
{
    "objectKey":   "logo/1001/20260424/avatar.png",
    "originName":  "avatar.png",
    "size":        98304,
    "contentType": "image/png",
    "accessUrl":   "http://127.0.0.1:9991/api/admin/resource/file/logo/1001/20260424/avatar.png",
    "resourceId":  10086
}

IMPORTANT

accessUrl 仅用于上传后即时预览,不要入库。入库值始终存 objectKey

查询时由 @OssUrlFill 注解自动将 objectKey 转换为完整访问 URL 返回给前端。

前端上传组件

所有上传组件统一使用 sceneCode 属性(旧版 dir 属性已废弃):

vue
<!-- 单图上传 -->
<Img :sceneCode="'admin.user.logo'" v-model="form.avatar" />

<!-- 多图上传 -->
<Imgs :sceneCode="'teacher.attachment'" v-model="form.images" />

<!-- 多文件上传 -->
<UploadFiles :sceneCode="'admin.user.logo'" v-model="form.fileList" />

<!-- 富文本编辑器 -->
<JoditEditor scene-code="system.richtext" v-model="form.content" />

@OssUrlFill 注解

数据库存储 objectKey,查询接口返回 VO 时需自动将其转换为可访问 URL。在 VO 字段上标注 @OssUrlFill,框架在 Controller 返回前自动完成替换:

java
public class UserVO {
    /**
     * 头像字段,数据库存储的是 objectKey(如 admin/20260430/avatar.jpg)
     * @OssUrlFill 会在返回时自动按 admin.user.logo 场景配置转换为完整 accessUrl
     */
    @OssUrlFill(sceneCode = "admin.user.logo")
    private String avatar;
}

Controller 无需额外处理,框架自动拦截 @RestController 方法返回值完成替换。

存储设计:数据库只存 objectKey

数据库存储的是 objectKey,而不是完整的访问 URL。

objectKey 是文件在存储介质中的相对路径,例如:

# 本地存储场景下的 objectKey 示例
admin/20260430/avatar.jpg

# OSS 存储场景下的 objectKey 示例
logo/admin/20260430/a3f9c1.jpg

完整的访问 URL 在运行时base-url(场景配置) + objectKey 动态拼装,不持久化到数据库。

为什么这样设计? 如果将完整 URL 存入数据库,一旦发生服务器 IP 变更、存储类型切换(本地 → OSS)、访问模式变更等,历史数据全部失效。而存储 objectKey 后,只需修改 oss.yml 中对应场景的 base-urlserve-mode配置一处,全局生效,数据库无需改动

完整数据流:

【上传时】
前端 → POST /resource/upload(携带 sceneCode)
     → 返回 { accessUrl, objectKey, resourceId, ... }
     → 业务代码:入库保存 objectKey(不保存 accessUrl)

【查询时】
数据库读取 objectKey
     → @OssUrlFill 切面根据 sceneCode 的当前配置(base-url / serve-mode)
       动态拼装或生成 accessUrl
     → 接口返回完整可访问的 accessUrl 给前端

相关文档