1. 项目概述
这个基于SpringBoot+Vue的个人网盘管理系统,是我在实际工作中沉淀下来的一套完整解决方案。它不同于市面上那些臃肿的企业级网盘,而是专门为个人和小团队设计的轻量级文件管理工具。核心功能包括文件上传下载、在线预览、分类管理、分享链接生成等,前后端完全分离的设计让系统具备了良好的扩展性。
我在开发过程中特别注重实际使用体验,比如针对大文件上传做了分片处理,对常见文件格式的预览做了优化,还加入了实用的回收站功能。系统采用的技术栈非常主流:后端是SpringBoot+MyBatis,前端是Vue+ElementUI,数据库选用MySQL,都是目前JavaWeb开发中最常用的技术组合。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 后端技术选型
SpringBoot作为后端框架的选择非常明确 - 它简化了传统Spring应用的配置和部署流程。我特别利用了这些特性:
- 自动配置:通过spring-boot-starter-web快速搭建Web环境
- 内嵌Tomcat:无需额外部署Servlet容器
- Actuator端点:方便监控应用运行状态
文件存储方面,我设计了两种方案:
- 本地存储:适合开发环境和小型部署
- 云存储接口:预留了对接七牛云、阿里云OSS的扩展点
数据库表设计核心是files表:
sql复制CREATE TABLE `files` (
`id` bigint NOT NULL AUTO_INCREMENT,
`file_name` varchar(255) NOT NULL,
`file_path` varchar(512) NOT NULL,
`file_size` bigint NOT NULL,
`file_type` varchar(50) NOT NULL,
`parent_id` bigint DEFAULT NULL,
`user_id` bigint NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`deleted` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_user_parent` (`user_id`,`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 前端技术方案
Vue3+Element Plus的组合提供了极佳的开发体验:
- 使用Vue Router实现前端路由控制
- Pinia管理全局状态(如用户登录信息)
- Axios封装了RESTful API调用
- 自定义hooks复用业务逻辑
文件上传组件是关键,我实现了这些特性:
- 拖拽上传
- 多文件并行上传
- 上传进度显示
- 断点续传(基于文件分片MD5校验)
3. 核心功能实现
3.1 文件上传下载
大文件上传采用分片策略:
- 前端计算文件MD5(使用spark-md5库)
- 将文件切分为2MB的块
- 并发上传各分片(限制3个并行请求)
- 服务端合并分片
后端关键代码:
java复制@PostMapping("/upload")
public Result upload(@RequestParam MultipartFile file,
@RequestParam(required = false) Long parentId,
HttpServletRequest request) {
// 校验用户权限
User user = getCurrentUser(request);
// 生成存储路径
String storePath = generateStorePath(user.getId(), file.getOriginalFilename());
// 保存文件
try (InputStream in = file.getInputStream()) {
storageService.store(in, storePath, file.getSize());
} catch (IOException e) {
log.error("文件存储失败", e);
return Result.error("上传失败");
}
// 记录文件元数据
FileRecord record = new FileRecord();
record.setFileName(file.getOriginalFilename());
record.setFilePath(storePath);
record.setFileSize(file.getSize());
record.setFileType(getFileType(file.getOriginalFilename()));
record.setParentId(parentId);
record.setUserId(user.getId());
fileMapper.insert(record);
return Result.success(record);
}
3.2 文件预览方案
针对不同文件类型采用不同预览策略:
| 文件类型 | 预览方案 | 技术实现 |
|---|---|---|
| 图片 | 直接显示 | <img>标签 |
| PDF.js | 前端渲染 | |
| Office | 转PDF预览 | LibreOffice无头模式 |
| 文本 | 代码高亮 | highlight.js |
| 视频 | 流媒体播放 | HLS.js |
4. 安全与性能优化
4.1 安全措施
-
文件上传安全:
- 白名单校验文件扩展名
- 检测文件真实类型(魔数校验)
- 重命名存储文件(避免路径遍历)
-
访问控制:
- JWT身份验证
- 细粒度权限检查(用户只能访问自己的文件)
- 分享链接设置有效期和密码
4.2 性能优化点
-
前端:
- 虚拟滚动优化大文件列表渲染
- Web Worker处理大文件hash计算
- 本地缓存文件目录结构
-
后端:
- 二级缓存(Redis+本地缓存)
- 异步处理耗时操作(如文件转码)
- 数据库读写分离(通过Spring AbstractRoutingDataSource实现)
5. 部署方案
5.1 开发环境部署
使用Docker Compose一键启动:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: netdisk
ports:
- "3306:3306"
volumes:
- ./data/mysql:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
frontend:
build: ./frontend
ports:
- "80:80"
5.2 生产环境建议
-
后端:
- 使用Nginx反向代理
- 配置HTTPS(Let's Encrypt免费证书)
- 启用Gzip压缩
- 设置合理的JVM参数
-
前端:
- 开启Brotli压缩
- 配置长期缓存(hash文件名)
- 启用HTTP/2
6. 常见问题解决
6.1 大文件上传中断
解决方案:
- 前端记录已上传分片
- 重新上传时先查询服务端已接收的分片
- 从第一个缺失的分片继续上传
6.2 内存溢出问题
典型场景:大文件上传时内存暴涨
优化方法:
- 配置Spring Boot文件上传缓冲区大小:
properties复制spring.servlet.multipart.max-file-size=2GB
spring.servlet.multipart.max-request-size=2GB
spring.servlet.multipart.file-size-threshold=2MB
- 使用临时文件存储替代内存缓冲:
java复制@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setLocation("/tmp");
return factory.createMultipartConfig();
}
7. 扩展与定制
系统设计时预留了多个扩展点:
- 存储引擎插件化:
java复制public interface StorageService {
void store(InputStream input, String path, long size);
InputStream load(String path);
void delete(String path);
}
- 文件处理管道:
java复制public interface FileProcessor {
boolean support(String fileType);
void process(Path file);
}
// 示例:图片压缩处理器
@Component
public class ImageCompressor implements FileProcessor {
@Override
public boolean support(String fileType) {
return fileType.startsWith("image/");
}
@Override
public void process(Path file) {
// 使用Thumbnailator进行图片压缩
}
}
这个项目从设计到实现历时两个月,期间遇到了不少挑战,特别是大文件处理和预览方案的选择。最终成型的系统虽然功能不算复杂,但在性能和用户体验上做了很多优化,代码结构也保持了良好的可维护性。对于想要学习现代Web全栈开发的朋友,这个项目涵盖了前后端交互、文件处理、性能优化等多个实用知识点,是个不错的练手项目。
