我又把自己的 Go 后台管理系统升级了一遍:文件管理、2GB 上传、私有文件预览、Docker 镜像全安排上了

欢迎大家提 https://github.com/Rodert/ShiyuAdmin/issues

大家好,我是 JavaPub。

最近又抽时间折腾了一下自己的开源项目 ShiyuAdmin

项目地址:

https://github.com/Rodert/ShiyuAdmin/

ShiyuAdmin 是我自己维护的一套通用后台管理系统,目前技术栈主要是:

  • Go
  • Gin
  • Gorm
  • React
  • Ant Design Pro
  • RBAC
  • PostgreSQL
  • Redis
  • Docker

最开始做它的时候,我的想法其实很简单:

以后再做管理后台,别每次都从登录、用户、角色、菜单、权限这些东西重新写一遍。

所以慢慢把用户管理、角色管理、菜单权限、部门管理、动态菜单、接口权限、操作日志、Redis 管理、系统监控、数据管理这些东西都加了进去。

但随着自己真正拿它去做项目,我越来越发现:

一个后台框架想真正"拿来就用",光有 RBAC 还远远不够。

所以最近又集中更新了一波。

这次我重点解决了几个我自己在实际项目里经常遇到的问题。


一、终于加入了完整的文件管理

这次比较大的一个更新,就是给 ShiyuAdmin 加了一套真正的 文件管理模块

这不是简单写一个:

text 复制代码
POST /upload

然后把文件扔到某个目录里就结束了。

我希望从一开始就把文件当成一个独立的基础设施来设计。

所以这次新增了两个核心模型:

text 复制代码
StorageConfig
MediaFile

也就是:

text 复制代码
存储配置
    ↓
文件元数据
    ↓
实际存储对象

文件本身和存储后端是分开的。

目前默认提供本地存储,初始化时会自动创建:

text 复制代码
本地存储
Driver: local
BasePath: ./data/uploads

但数据模型里已经预留了:

text 复制代码
local
s3
oss

以及:

text 复制代码
Endpoint
Bucket
PublicURL
AccessKey
SecretKey

这些字段。

这意味着后面要接:

text 复制代码
AWS S3
Cloudflare R2
阿里云 OSS
腾讯云 COS
MinIO

实际上就比较顺了。

我不太喜欢那种一开始把文件上传路径硬编码死,后面要上对象存储的时候再推倒重来的做法。

既然是通用后台,就应该尽量把扩展能力提前留出来。


二、文件不只是上传,还要能真正"管理"

有了存储还不够。

后台里现在已经加入了完整的文件列表和管理能力。

包括:

text 复制代码
文件列表
文件搜索
分页
上传
下载
删除
回收站
恢复

而且这里的删除并不是直接物理删除。

我用了软删除的方式,把删除后的文件放进"回收站"。

对应接口也拆开了:

text 复制代码
GET    /files
GET    /files/recycle-bin

POST   /files/upload

GET    /files/:code/download

DELETE /files/:code

POST   /files/:code/restore

这样用户误删文件以后,还有机会恢复。

文件记录里面也不只是保存一个路径,而是记录了:

text 复制代码
FileCode
StorageID
OriginalName
ObjectKey
MimeType
Size
SHA256
AccessLevel
UploaderCode

比如 SHA256 后面可以继续做:

text 复制代码
文件校验
重复文件判断
内容寻址
安全扫描

这些东西。

这也是我现在做 ShiyuAdmin 一个比较明确的思路:

不只是把页面做出来,而是尽量把以后真正做业务需要的扩展空间留出来。


三、文件权限也接进了 RBAC

既然 ShiyuAdmin 本身就是一个 RBAC 后台,那么文件系统肯定不能自己另搞一套权限。

所以这次直接把文件管理接进了原来的权限体系。

目前主要拆成:

text 复制代码
system:file:list
system:file:upload
system:file:delete

也就是说可以做到:

text 复制代码
A 角色只能查看文件

B 角色可以查看 + 上传

C 角色拥有查看 + 上传 + 删除权限

而不是只要登录后台,就能随便上传和删除。

很多后台系统一开始文件上传只是一个辅助功能。

但随着业务越来越复杂,合同、图片、Excel、PDF、附件、视频全部往里面塞以后,文件本身其实已经变成非常重要的一类业务数据。

这时候权限就不能再靠前端"隐藏一个按钮"来解决了。

接口权限必须一起做。


四、单文件上传直接放到了 2 GiB

这个更新其实还有一个挺有意思的小坑。

文件模块刚做完的时候,应用层虽然支持大文件,但部署以后发现:

Nginx 先把请求拦了。

所以后面又专门提交了一次修复:

text 复制代码
fix: allow 2GiB multipart uploads

在 Nginx 层增加了:

nginx 复制代码
client_max_body_size 2050m;

为什么不是刚好 2048m?

因为 multipart/form-data 本身还有 boundary 等额外数据,需要留一点空间。

后端本身也做了大小限制:

go 复制代码
const maxUploadSize int64 = 2 << 30

并通过 MaxBytesReader 控制请求大小。

所以现在单文件最大可以做到:

text 复制代码
2 GiB

图片、PDF、压缩包,甚至一些视频文件都基本够用了。

这个地方也算一个挺典型的工程问题:

一个功能"代码支持",不代表真正部署出去以后就支持。

中间可能还有:

text 复制代码
浏览器
CDN
Cloudflare
Nginx
网关
后端框架
应用服务器
对象存储

任何一层限制都可能导致上传失败。


五、私有文件终于可以在线预览了

文件管理做好以后,我很快又遇到一个问题。

如果文件是私有的,直接把 URL 塞给浏览器并不合适。

因为它需要经过登录鉴权和 RBAC 权限校验。

于是又加了一次提交:

text 复制代码
feat: preview private media files

后端新增:

text 复制代码
GET /files/:code/preview

并且仍然要求:

text 复制代码
system:file:list

权限。

前端不会直接暴露一个裸文件地址,而是带着 Bearer Token 请求文件,然后拿到 Blob,再创建临时 URL 用来展示。

目前支持的在线预览包括:

text 复制代码
图片
PDF
文本文件

图片直接展示;

PDF 和文本可以通过 iframe 预览;

其他暂时不支持的格式则提示用户下载查看。

这个设计我个人还是比较喜欢的。

因为:

text 复制代码
登录鉴权
    ↓
RBAC 权限验证
    ↓
读取文件
    ↓
返回 Blob
    ↓
浏览器临时预览

整个链路仍然在后台的权限控制范围内。

而不是为了图方便,把原本应该是私有的文件变成公开 URL。


六、另外一个小功能:主题偏好

这一波更新里还顺手完善了后台的主题偏好。

这个功能相比文件管理当然不算大,但对于一个每天都要打开的后台来说,体验还是挺重要的。

后台系统和普通网站不太一样。

很多运营、管理员、开发人员可能一天要盯着它几个小时。

所以类似:

text 复制代码
主题
布局
界面偏好

这些东西我后面也会继续完善。

这类功能单独拿出来没什么惊艳的,但一个成熟后台往往就是由这些"小东西"一点点堆出来的。


七、这次我更在意的,其实是 Docker 部署

除了业务功能,这次我还重新整理了一遍整个项目的 Docker 部署方式。

这部分我觉得反而非常重要。

以前很多开源后台都是:

bash 复制代码
git clone

然后:

bash 复制代码
npm install
npm run build

go build

docker build

服务器自己从源码开始折腾。

这种方式开发阶段没问题。

但是部署多了以后真的很烦。

所以这次我直接做了一套 统一应用镜像


八、前端 + 后端打成一个镜像

现在根目录增加了一个多阶段 Dockerfile。

整个构建过程大致是:

text 复制代码
Node 20
   ↓
构建 React 前端

Go 1.23
   ↓
编译 Go Backend

Nginx Alpine
   ↓
放入前端静态文件

Supervisor
   ↓
同时管理 Nginx + Go API

也就是说:

text 复制代码
React
+
Go API
+
Nginx
+
Supervisor

最终全部变成:

text 复制代码
一个 Docker Image

而不是服务器上跑一堆分散的东西。

这样以后部署的时候简单很多。


九、GitHub Actions 自动构建 GHCR 镜像

这个是我这次比较喜欢的一个改动。

现在每次 Push 代码,GitHub Actions 都可以自动:

text 复制代码
Checkout
    ↓
Docker Build
    ↓
生成镜像
    ↓
Push 到 GHCR

也就是:

text 复制代码
GitHub Container Registry

对应镜像:

text 复制代码
ghcr.io/<owner>/<repo>

Action 会自动生成多种标签,包括:

text 复制代码
branch
tag
sha-xxx
YYYYMMDD-HHmmss
latest

其中默认分支会额外维护 latest

这样服务器以后根本不用再编译项目。

只需要:

bash 复制代码
docker compose pull
docker compose up -d --no-build

就行了。

整个发布流程变成:

text 复制代码
我 Push GitHub
        ↓
GitHub Actions
        ↓
构建 ShiyuAdmin Image
        ↓
GHCR
        ↓
服务器 docker pull
        ↓
启动

这才是我比较喜欢的开源项目部署方式。


十、为什么我要把本地 Compose 和线上部署拆开?

另外我还专门做了一次:

text 复制代码
chore: separate local compose and disable auto fly deploy

把:

text 复制代码
docker-compose.local.yml

和正式部署配置区分开。

同时 Fly.io 不再跟着每次 main push 自动部署,而是改成手动触发。

原因也很简单。

以前一个仓库同时承担:

text 复制代码
开发环境
测试环境
演示环境
线上环境
镜像发布

很容易越做越乱。

现在我的思路逐渐变成:

text 复制代码
源码
    ↓
CI Build
    ↓
标准 Docker Image
    ↓
不同环境自己决定怎么运行

GHCR 负责"发布镜像"。

Fly.io、自己的服务器、云服务器等则只是不同的"运行环境"。

这样两件事情就解耦了。

我认为这比"GitHub 一 Push 就自动把某台服务器更新掉"更加适合作为一个公共开源项目的默认方案。


十一、现在的 ShiyuAdmin 到什么程度了?

如果把最近几个月加进去的东西放到一起,现在基本已经有:

text 复制代码
用户管理
角色管理
菜单管理
部门管理

RBAC 权限
动态菜单
接口权限
数据权限

个人中心
登录日志
操作日志

Redis 缓存管理
数据管理
系统监控

Dashboard
访问态势
可视化图表

文件管理
文件上传
文件下载
文件预览
文件回收站
存储配置

Docker Compose
统一应用镜像
GitHub Actions
GHCR 自动发布

项目本身采用前后端分离架构,后端是 Go + Gin + Gorm,前端是 React + Umi Max + Ant Design Pro;README 目前也已经把它定位成适合快速搭建中后台、学习 RBAC 或作为新业务基础脚手架的通用后台系统。

所以现在我自己也不太愿意把它单纯定义成一个:

"Go 后台管理系统 Demo"。

我更希望它慢慢变成一个:

真正能拿来作为新项目基础工程的后台底座。


十二、接下来还会继续加什么?

文件系统现在只是第一版。

从目前的数据结构其实已经能看出来,我后面比较想继续做:

text 复制代码
Cloudflare R2
AWS S3
MinIO
阿里云 OSS
腾讯云 COS

这类对象存储。

然后继续完善:

text 复制代码
文件分类
目录
批量操作
图片缩略图
视频预览
文件引用关系
存储空间统计
上传进度
分片上传
断点续传

另外还有一个方向,是继续降低部署成本。

理想状态就是:

bash 复制代码
docker compose up -d

甚至:

bash 复制代码
docker run ...

就能得到一整套可以直接开发业务的后台。


最后

我一直觉得:

自己维护一个开源项目,最有意思的地方其实并不是一次性写出多少代码。

而是你真的拿它去做项目以后,会不断发现:

text 复制代码
这里还不够方便
那里不够安全
这个地方不好部署
那个功能缺了一块

然后一点一点补上。

ShiyuAdmin 也是这样。

它不是某一天突然写出来的,而是在我自己的实际开发过程中,一点点长出来的。

如果你最近正好在学:

text 复制代码
Go
Gin
Gorm
React
Ant Design Pro
RBAC
Docker
GitHub Actions

或者正准备做一个自己的后台管理系统,可以拿去参考或者直接改。

项目完全开源。

GitHub:

https://github.com/Rodert/ShiyuAdmin/

觉得项目还不错的话,也欢迎给个 Star。

有 Bug、功能建议,也欢迎直接提 Issue。

我还会继续更新。

一起成为勇猛精进的人类。

相关推荐
动力 continue1 小时前
Python 元类与异常类:类的“制造工厂”与“报错定制师”
开发语言·python·制造
quantdash_cc1 小时前
基于 QuantDash 5 分钟 K 线的网格交易策略参数网格搜索寻优实战
android·开发语言·pandas·量化·quantdash
147API1 小时前
Python批量生成蒸馏数据,并发、重试、幂等和断点续跑
开发语言·jvm·python
青 春 记 忆1 小时前
零基础入门python04:用注册校验理解字典、集合和条件判断
开发语言·vscode·python·python3.11
kels88991 小时前
实战排坑:黄金实时API开发,XAUUSD Tick报文异常处理实践
开发语言·python·websocket·网络协议·信息可视化
阿pin1 小时前
Java随笔-JDK7 HashMap头插法为何能导致死循环?
java·开发语言·hashmap
FBI HackerHarry浩1 小时前
Pandas 库中用于分类变量独热编码(One-Hot Encoding)的函数 pd.get_dummies() 函数
开发语言·人工智能·python·pandas
名字还没想好☜1 小时前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
Zhu7582 小时前
在docker环境部署frp
运维·docker·容器