go语言编写的文件服务器
简易用户文件系统
项目地址:https://github.com/jianingdai/filesysByGo
使用
在
08
文件夹中使用以下命令来启动服务程序1
go run ./cmd/filesys/main.go
!!!第一次运行时需要在
08
文件夹下依次运行以下两个命令:1
2go run ./cmd/init_db/main.go
go run ./cmd/gen/main.go
文件管理系统的默认开启端口为 8080 端口。
访问运行服务程序主机的 8080 端口就可以查看并且测试文件系统,不过前端界面只是测试界面,是一个很简陋的测试界面。
功能概述
- 实现一个简易的用户文件系统。
- 每个用户拥有独立的文件树,节点类型包括文件和文件夹。
- 每个文件或文件夹都有唯一 ID,根目录文件夹 ID 为 0。
- 支持文件和文件夹的基本操作接口。
- 系统默认自带管理员账号
admin
,仅管理员可创建其他用户。 - 同一文件夹下文件和文件夹均不可重名,若重名则自动重命名(规则参考 Windows)。
- 文件支持版本管理,版本号从 1 开始递增,当前版本号最大。
高级功能:客户端配合服务端使用 rsync 差分算法实现历史版本增量上传(后续版本实现)。- 文件存储于工程根目录下的
data
目录,需考虑磁盘文件清理。 - 推荐使用 Postman 进行接口测试,支持简单前端页面展示更佳。
技术栈
分层设计
该项目采用分层设计,主要分为以下几层:
- cmd: 包含可执行文件,例如:
filesys
: 主程序入口,负责初始化数据库连接、启动 utils.StartSessionCleaner() 定时清理过期 session 的协程,以及初始化并启动 router。init_db
: 初始化数据库,创建表结构并创建默认管理员用户。gen
: 使用 GORM Gen 自动生成数据库访问代码。- 注意: 首次运行项目时,需要先运行
init_db
初始化数据库,然后运行gen
生成数据库访问代码。
- 注意: 首次运行项目时,需要先运行
- dao: 数据库访问层,包含自动生成的数据库操作代码。 使用 GORM Gen 根据数据库表结构自动生成,位于 dao 目录。
- 该层主要通过 GORM 提供的 API 进行数据库操作,例如:
Create
: 创建数据。Find
: 查询数据。Update
: 更新数据。Delete
: 删除数据。
- 该层主要通过 GORM 提供的 API 进行数据库操作,例如:
- models: 数据库模型定义,定义了数据库表的结构体。 位于 models_def 目录。
例如,
User
结构体定义了用户表的结构:1
2
3
4
5
6
7type User struct {
ID int64 `gorm:"primaryKey;autoIncrement"`
Username string `gorm:"type:varchar(255);not null;unique"`
Password string `gorm:"type:varchar(255);not null"`
CreatedAt time.Time
UpdatedAt time.Time
}File
结构体定义了文件表的结构:1
2
3
4
5
6
7
8
9
10
11
12
13type File struct {
ID int64 `gorm:"primaryKey;autoIncrement"`
UserID int64 `gorm:"not null"`
ParentID int64 `gorm:"not null"`
Name string `gorm:"type:varchar(255);not null"`
Type int `gorm:"not null"` // 0: 文件夹, 1: 文件
Size int64 `gorm:"not null"`
Hash string `gorm:"type:varchar(255)"`
Version int `gorm:"not null;default:1"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
- endpoint: 接口处理层,负责接收 HTTP 请求、参数校验、调用 service 层处理业务逻辑,并将结果返回给客户端。
该层使用了 Gin 框架提供的 API 进行路由注册和请求处理。
例如,
CreateUser
函数处理创建用户请求:1
2
3
4
5
6
7func CreateUser(c *gin.Context) {
// ...
if err := s.CreateUser(username, password); err != nil {
// ...
}
// ...
}
- service: 业务逻辑层,负责实现具体的业务逻辑,例如:
- 文件上传、下载、删除、复制、移动、重命名等。
- 用户登录、创建等。
- 该层主要调用 dao 层提供的 API 进行数据库操作,并进行必要的业务逻辑处理。
- middleware: 中间件层,负责处理一些通用的逻辑,例如:
- 身份验证:
AuthMiddleware
验证用户身份,并将用户 ID 存储在上下文中。- 该中间件通过检查 Cookie 中的
sid
来验证用户身份。 - 如果用户已登录,则将用户 ID 存储在 Gin 的 Context 中,方便后续处理函数使用。
- 该中间件通过检查 Cookie 中的
- 权限验证:
FilePermissionMiddleware
验证用户是否有权限访问指定文件。- 该中间件检查当前用户是否有权限访问指定文件,如果没有权限则返回 403 Forbidden 错误。
- 身份验证:
- frontend: 前端静态资源,包含 HTML、CSS 和 JavaScript 文件。
- 前端代码位于
frontend
目录下。 - 前端使用 JavaScript 调用后端 API,实现文件管理功能。
- 前端代码位于
- utils: 包含一些实用工具函数,例如:
utils.StartSessionCleaner()
:定时清理过期 session。- 该函数启动一个 Goroutine,定时清理过期的 session 数据。
- Session 过期时间默认为 24 小时。
- router: 路由配置,负责将 HTTP 请求路由到相应的 endpoint 处理函数。
- 路由配置位于
router/router.go
文件中。 - 该文件使用了 Gin 框架提供的 API 进行路由注册。
- 路由配置位于
接口说明
登录接口
POST /login
用户登录,返回sid
,后续接口需在 Cookie 中携带sid
。- 请求体参数:
username
、password
。 - 成功登录后,服务器会生成一个 session ID,并将其存储在 Cookie 中。
- 请求体参数:
管理接口(仅管理员)
POST /api/user/create
创建新用户。- 需要管理员权限。
- 请求体参数:
username
、password
。 - 管理员用户可以通过该接口创建新的用户账号。
文件接口
POST /api/file/{file_id}/new
新建文件夹,file_id
为父目录 ID,返回文件夹信息。- 请求体参数:
name
(文件夹名称) - 在指定的父目录下创建一个新的文件夹。
- 请求体参数:
POST /api/file/{file_id}/upload
上传文件,file_id
为父目录 ID,文件二进制内容放在请求体,返回文件信息。- 请求体参数:文件二进制数据
- 在指定的父目录下上传一个新的文件。
POST /api/file/{file_id}/update
更新文件,文件二进制内容放在请求体,返回文件信息。- 请求体参数:文件二进制数据
- 更新指定文件的内容。
DELETE /api/file/{file_id}
删除文件或文件夹。- 删除指定的文件或文件夹。
POST /api/file/{file_id}/copy
复制文件或文件夹。- 请求体参数:
dest_id
(目标父目录 ID) - 将指定的文件或文件夹复制到目标父目录下。
- 请求体参数:
POST /api/file/{file_id}/move
移动文件或文件夹。- 请求体参数:
dest_id
(目标父目录 ID) - 将指定的文件或文件夹移动到目标父目录下。
- 请求体参数:
POST /api/file/{file_id}/rename
重命名文件或文件夹。- 请求体参数:
new_name
(新的名称) - 重命名指定的文件或文件夹。
- 请求体参数:
GET /api/file/{file_id}
获取文件或文件夹信息。- 返回文件或文件夹的详细信息,例如:ID、名称、类型、大小、创建时间等。
GET /api/file/{file_id}/list
获取文件夹下的文件和文件夹列表。- 返回指定文件夹下的所有文件和文件夹的列表。
GET /api/file/{file_id}/content
下载文件内容。- 返回指定文件的二进制内容。
GET /api/file/{file_id}/version/{ver_num}/content
下载指定历史版本的文件内容。- 返回指定历史版本的文件二进制内容。
GET /api/file/{file_id}/versions
获取文件的版本历史列表。- 返回指定文件的所有历史版本列表。
数据库表结构
users: 存储用户信息。
1
2
3
4
5
6
7CREATE TABLE `users` (
`id` integer PRIMARY KEY AUTOINCREMENT,
`username` varchar(255) NOT NULL UNIQUE,
`password` varchar(255) NOT NULL,
`created_at` datetime,
`updated_at` datetime
);files: 存储文件和文件夹信息。
1
2
3
4
5
6
7
8
9
10
11
12
13CREATE TABLE `files` (
`id` integer PRIMARY KEY AUTOINCREMENT,
`user_id` integer NOT NULL,
`parent_id` integer NOT NULL,
`name` varchar(255) NOT NULL,
`type` integer NOT NULL, -- 0: 文件夹, 1: 文件
`size` integer NOT NULL,
`hash` varchar(255),
`version` integer NOT NULL DEFAULT 1,
`created_at` datetime,
`updated_at` datetime,
`deleted_at` datetime
);