当前位置:   article > 正文

Springboot+vue实现前后端分离网盘存储系统_@operation

@operation

项目编号:BS-XX-094

## 功能介绍

1. 多文件格式分类查看

2. 支持网格、表格视图、时间线三种展示视图

3. 支持极速秒传功能,提高上传效率

4. 多人上传同一文件,可多人并行上传,共享他人上传进度,极大提高上传效率

5. 拒绝冗余,每份文件只存一份,提高硬盘使用效率

6. 上传文件前台实时显示上传文件进度,上传速率,百分比等信息

7. 安全的下载机制,断点下载,权限校验,他人拿到了下载地址也无法下载您的文件

8. 支持视频音频播放,进度条拖拽,倍速播放

9. 拥有回收站功能,妈妈再也不怕我误删数据了

10. 高效的垃圾回收机制




## 软件架构

该项目采用前后端分离的方式进行开发和部署,主要用到以下关键技术

**前端**:Element UI、Vue CLI@3、Node.js、Webpack

**后台**:Spring Boot、Spring Data Jpa、Spring Security

**数据库** : MySQL或H2

**数据结构**:递归算法,树的遍历和插入...


 

下面展示一下系统部分功能:

用户登陆注册:

网盘管理主页

文件上传

新建文件夹

移动文件

视频文件在线播放

回收站管理:可以对文件进行恢复和删除

 

项目核心代码:

  1. package io.ddisk.controller;
  2. import io.ddisk.domain.dto.PageDTO;
  3. import io.ddisk.domain.enums.FileTypeEnum;
  4. import io.ddisk.domain.vo.DirTreeNode;
  5. import io.ddisk.domain.vo.FileVO;
  6. import io.ddisk.domain.vo.LoginUser;
  7. import io.ddisk.domain.vo.PathNodeVO;
  8. import io.ddisk.domain.vo.base.PageVO;
  9. import io.ddisk.service.UserFileService;
  10. import io.ddisk.utils.SpringWebUtils;
  11. import io.swagger.v3.oas.annotations.Operation;
  12. import io.swagger.v3.oas.annotations.Parameter;
  13. import io.swagger.v3.oas.annotations.Parameters;
  14. import io.swagger.v3.oas.annotations.tags.Tag;
  15. import org.hibernate.validator.constraints.Length;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.http.ResponseEntity;
  18. import org.springframework.validation.annotation.Validated;
  19. import org.springframework.web.bind.annotation.*;
  20. import javax.validation.constraints.NotBlank;
  21. import javax.validation.constraints.NotEmpty;
  22. import javax.validation.constraints.NotNull;
  23. import javax.validation.constraints.Null;
  24. import java.util.List;
  25. import java.util.Map;
  26. @Tag(name = "File", description = "该接口为文件接口,主要用来做一些文件的基本操作,如创建目录,删除,移动,复制等。")
  27. @Validated
  28. @RestController
  29. @RequestMapping("/file")
  30. public class FileController {
  31. @Autowired
  32. private UserFileService userFileService;
  33. @Operation(summary = "获取目录及文件", description = "前端提供父目录和分页数据,返回该文件夹下的这些数据", tags = {"file"})
  34. @GetMapping(value = "/list")
  35. @Parameters({
  36. @Parameter(name = "pid", description = "用户文件目录id,需要登录用户的文件", required = true)
  37. })
  38. public ResponseEntity<PageVO<FileVO>> getFileList(@NotNull PageDTO page, @Length(min = 32, max = 32) @RequestParam(required = false) String pid) {
  39. LoginUser user = SpringWebUtils.requireLogin();
  40. PageVO<FileVO> fileListPage = userFileService.listTheDir(user.getId(), pid, page);
  41. return ResponseEntity.ok(fileListPage);
  42. }
  43. @Operation(summary = "获取某类型文件", description = "获取某一类型文件,例如图片、视频、文档等", tags = {"file"})
  44. @GetMapping(value = "/list/type")
  45. @Parameters({
  46. @Parameter(name = "fileType", description = "文件类型,图片文件,视频文件等", required = true)
  47. })
  48. public ResponseEntity<PageVO<FileVO>> getFileListByType(@NotNull PageDTO page, @NotNull FileTypeEnum fileType) {
  49. LoginUser user = SpringWebUtils.requireLogin();
  50. PageVO<FileVO> fileListPage = userFileService.listTheTypeFile(user.getId(), fileType, page);
  51. return ResponseEntity.ok(fileListPage);
  52. }
  53. @Operation(summary = "文件搜索", description = "模糊搜索文件名", tags = {"file"})
  54. @GetMapping(value = "/search")
  55. @Parameters({
  56. @Parameter(name = "filename", description = "模糊搜索文件名", required = true)
  57. })
  58. public ResponseEntity<PageVO<FileVO>> searchFile(@NotNull PageDTO page, @NotBlank String filename) {
  59. PageVO<FileVO> fileListPage = userFileService.searchFile(filename, page);
  60. return ResponseEntity.ok(fileListPage);
  61. }
  62. @Operation(summary = "获取目录树", description = "文件移动的时候需要用到该接口,用来展示目录树,展示机制为饱汉模式", tags = {"file"})
  63. @GetMapping(value = "/dir/tree")
  64. public ResponseEntity<DirTreeNode> getDirTree() {
  65. LoginUser user = SpringWebUtils.requireLogin();
  66. DirTreeNode tree = userFileService.dirTree(user.getId());
  67. return ResponseEntity.ok(tree);
  68. }
  69. @Operation(summary = "查询回收站文件", description = "查询某用户回收站所有文件", tags = {"file"})
  70. @GetMapping(value = "/list/recycle")
  71. public ResponseEntity<PageVO<FileVO>> listRecycleBin(@NotNull PageDTO page) {
  72. LoginUser user = SpringWebUtils.requireLogin();
  73. PageVO<FileVO> fileListPage = userFileService.listRecycle(user.getId(), page);
  74. return ResponseEntity.ok(fileListPage);
  75. }
  76. @Operation(summary = "父节点列表", description = "用于显示父路径,字典key为文件id", tags = {"file"})
  77. @GetMapping(value = "/path/tree")
  78. public ResponseEntity<Map<String, PathNodeVO>> getPathTree() {
  79. LoginUser user = SpringWebUtils.requireLogin();
  80. Map<String, PathNodeVO> pathTreeMap = userFileService.getPathTreeMap(user.getId());
  81. return ResponseEntity.ok(pathTreeMap);
  82. }
  83. @Operation(summary = "移动文件", description = "移动文件", tags = {"file"})
  84. @PostMapping(value = "/move")
  85. @Parameters({
  86. @Parameter(name = "from", description = "移动文件id", required = true),
  87. @Parameter(name = "to", description = "目标文件夹id", required = true)
  88. })
  89. public ResponseEntity<Void> move(@NotBlank @Length(min = 32, max = 32) String from, @Length(min = 32, max = 32) @RequestParam(required = false) String to) {
  90. userFileService.move(from, to);
  91. return ResponseEntity.ok().build();
  92. }
  93. @Operation(summary = "移动文件", description = "批量移动文件", tags = {"file"})
  94. @PostMapping(value = "/batch/move")
  95. @Parameters({
  96. @Parameter(name = "from", description = "移动文件id列表", required = true),
  97. @Parameter(name = "to", description = "目标文件夹id", required = true)
  98. })
  99. public ResponseEntity<Void> batchMove(@RequestParam(value = "from") @NotEmpty List<String> from, @Length(min = 32, max = 32)@RequestParam(required = false) String to) {
  100. userFileService.move(from, to);
  101. return ResponseEntity.ok().build();
  102. }
  103. @Operation(summary = "创建目录", description = "创建文件夹", tags = {"file"})
  104. @PostMapping(value = "/mkdir")
  105. @Parameters({
  106. @Parameter(name = "pid", description = "父目录id", required = false),
  107. @Parameter(name = "name", description = "目录名", required = true),
  108. })
  109. public ResponseEntity<Void> mkdir(@RequestParam(required = false) @Length(min = 32, max = 32) String pid, @NotBlank String name) {
  110. LoginUser user = SpringWebUtils.requireLogin();
  111. userFileService.mkdir(user.getId(), pid, name);
  112. return ResponseEntity.ok().build();
  113. }
  114. @Operation(summary = "重命名", description = "重命名文件名和扩展名", tags = {"file"})
  115. @PostMapping(value = "/rename")
  116. @Parameters({
  117. @Parameter(name = "userFileId", description = "文件id", required = true),
  118. @Parameter(name = "filename", description = "文件基础名", required = true),
  119. @Parameter(name = "extension", description = "文件扩展名", required = true),
  120. })
  121. public ResponseEntity<Void> rename(@NotBlank @Length(min = 32, max = 32) String userFileId, @NotBlank String filename, String extension) {
  122. userFileService.rename(userFileId, filename, extension);
  123. return ResponseEntity.ok().build();
  124. }
  125. @Operation(summary = "删除文件", description = "删除文件或文件夹", tags = {"file"})
  126. @PostMapping(value = "/delete")
  127. @Parameters({
  128. @Parameter(name = "userFileId", description = "文件id", required = true),
  129. })
  130. public ResponseEntity<Void> delete(@NotBlank @Length(min = 32, max = 32) String userFileId) {
  131. userFileService.delete(userFileId);
  132. return ResponseEntity.ok().build();
  133. }
  134. @Operation(summary = "批量删除文件", description = "批量删除文件或文件夹", tags = {"file"})
  135. @PostMapping(value = "/batch/delete")
  136. @Parameters({
  137. @Parameter(name = "userFileIds", description = "文件id列表", required = true),
  138. })
  139. public ResponseEntity<Void> batchDelete(@NotEmpty @RequestParam(value = "userFileIds") List<String> userFileIds) {
  140. userFileService.delete(userFileIds);
  141. return ResponseEntity.ok().build();
  142. }
  143. @Operation(summary = "恢复文件", description = "恢复回收站文件或文件夹", tags = {"file"})
  144. @PostMapping(value = "/recover")
  145. @Parameters({
  146. @Parameter(name = "userFileId", description = "文件id", required = true),
  147. })
  148. public ResponseEntity<Void> recover(@NotBlank @Length(min = 32, max = 32) String userFileId) {
  149. userFileService.recover(userFileId);
  150. return ResponseEntity.ok().build();
  151. }
  152. @Operation(summary = "批量恢复文件", description = "批量恢复回收站文件或文件夹", tags = {"file"})
  153. @PostMapping(value = "/batch/recover")
  154. @Parameters({
  155. @Parameter(name = "userFileIds", description = "文件id列表", required = true),
  156. })
  157. public ResponseEntity<Void> batchRecover(@NotEmpty @RequestParam(value = "userFileIds") List<String> userFileIds) {
  158. userFileService.recover(userFileIds);
  159. return ResponseEntity.ok().build();
  160. }
  161. @Operation(summary = "删除回收站文件", description = "真正的删除文件接口,删除回收站里的文件", tags = {"file"})
  162. @PostMapping(value = "/delete/recycle")
  163. @Parameters({
  164. @Parameter(name = "userFileId", description = "文件id", required = true),
  165. })
  166. public ResponseEntity<Void> deleteFromRecycleBin(@NotBlank @Length(min = 32, max = 32) String userFileId) {
  167. userFileService.deleteFromRecycleBin(userFileId);
  168. return ResponseEntity.ok().build();
  169. }
  170. @Operation(summary = "批量删除回收站文件", description = "真正的删除文件接口,删除回收站里的文件", tags = {"file"})
  171. @PostMapping(value = "/batch/delete/recycle")
  172. @Parameters({
  173. @Parameter(name = "userFileIds", description = "文件id列表", required = true),
  174. })
  175. public ResponseEntity<Void> batchDeleteFromRecycleBin(@RequestParam(value = "userFileIds") @NotEmpty List<String> userFileIds) {
  176. userFileService.deleteFromRecycleBin(userFileIds);
  177. return ResponseEntity.ok().build();
  178. }
  179. }

  1. package io.ddisk.controller;
  2. import io.ddisk.domain.dto.FileDTO;
  3. import io.ddisk.domain.dto.FileUploadDTO;
  4. import io.ddisk.domain.dto.MergeFileDTO;
  5. import io.ddisk.domain.entity.FileEntity;
  6. import io.ddisk.domain.vo.LoginUser;
  7. import io.ddisk.domain.vo.UploadFileVO;
  8. import io.ddisk.service.FileService;
  9. import io.ddisk.service.FileShareService;
  10. import io.ddisk.utils.ResponseUtils;
  11. import io.ddisk.utils.SpringWebUtils;
  12. import io.swagger.v3.oas.annotations.Operation;
  13. import io.swagger.v3.oas.annotations.Parameter;
  14. import io.swagger.v3.oas.annotations.Parameters;
  15. import io.swagger.v3.oas.annotations.tags.Tag;
  16. import jodd.bean.BeanCopy;
  17. import lombok.extern.slf4j.Slf4j;
  18. import org.hibernate.validator.constraints.Length;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.http.ResponseEntity;
  21. import org.springframework.validation.annotation.Validated;
  22. import org.springframework.web.bind.annotation.*;
  23. import javax.validation.constraints.NotBlank;
  24. import java.util.Collection;
  25. import java.util.Objects;
  26. @Slf4j
  27. @Tag(name = "FileTransfer", description = "该接口为文件传输接口,主要用来做文件的上传和下载")
  28. @RequestMapping("transfer")
  29. @Validated
  30. @RestController
  31. public class FileTransferController {
  32. @Autowired
  33. private FileService fileService;
  34. @Autowired
  35. private FileShareService fileShareService;
  36. @Operation(summary = "极速上传", description = "校验文件MD5判断文件是否存在,如果存在直接上传成功并返回skipUpload=true,如果不存在返回skipUpload=false")
  37. @GetMapping("upload")
  38. @ResponseBody
  39. public ResponseEntity<UploadFileVO> uploadFileSpeed(@Validated FileUploadDTO fileUploadDto){
  40. LoginUser user = SpringWebUtils.requireLogin();
  41. FileEntity fileEntity = fileService.speedUpload(user.getId(), fileUploadDto);
  42. Collection<Integer> uploaded = fileService.getUploaded(fileUploadDto.getIdentifier(), fileUploadDto.getChunkSize());
  43. return ResponseEntity.ok(new UploadFileVO(false, Objects.nonNull(fileEntity), uploaded));
  44. }
  45. @Operation(summary = "上传文件", description = "真正的上传文件接口")
  46. @PostMapping("upload")
  47. public ResponseEntity<UploadFileVO> uploadChunk(@Validated FileUploadDTO fileUploadDto) {
  48. LoginUser user = SpringWebUtils.requireLogin();
  49. Collection<Integer> uploaded = fileService.upload(user.getId(), fileUploadDto);
  50. return ResponseEntity.ok(new UploadFileVO(uploaded.size()==fileUploadDto.getTotalChunks(), false, uploaded));
  51. }
  52. @Operation(summary = "下载文件", description = "文件下载接口,保证文件安全,阻止非法用户下载")
  53. @GetMapping("download/{userFileId}")
  54. @Parameters({
  55. @Parameter(name = "userFileId", description = "用户文件id,需要登录用户的文件", required = true)
  56. })
  57. public void downloadFile(@PathVariable @NotBlank @Length(min = 32, max = 32) String userFileId){
  58. LoginUser user = SpringWebUtils.requireLogin();
  59. FileDTO fileDTO = fileService.getFileResource(user.getId(), user.getRole(), userFileId);
  60. ResponseUtils.sendFile(fileDTO);
  61. }
  62. @Operation(summary = "下载文件", description = "文件下载接口,保证文件安全,阻止非法用户下载")
  63. @GetMapping("/anonymous/download/{shareId}")
  64. @Parameters({
  65. @Parameter(name = "userFileId", description = "用户文件id,需要登录用户的文件", required = true)
  66. })
  67. public void anonymousDownloadFile(@PathVariable @NotBlank @Length(min = 32, max = 32) String shareId){
  68. FileDTO fileDTO = fileShareService.getFileResource(shareId);
  69. ResponseUtils.sendFile(fileDTO);
  70. }
  71. @Operation(summary = "获取略缩图", description = "略缩图获取,用于图片类型文件的略缩图和头像")
  72. @GetMapping("thumbnail/{userFileId}")
  73. @Parameters({
  74. @Parameter(name = "userFileId", description = "用户文件id,需要登录用户的文件", required = true)
  75. })
  76. public void thumbnail(@PathVariable @NotBlank @Length(min = 32, max = 32) String userFileId){
  77. LoginUser user = SpringWebUtils.requireLogin();
  78. FileDTO fileDTO = fileService.getThumbnail(user.getId(), userFileId);
  79. ResponseUtils.sendFile(fileDTO);
  80. }
  81. @Operation(summary = "合并", description = "合并上传的切片文件")
  82. @PostMapping("merge")
  83. public ResponseEntity<Void> mergeFile(@Validated @RequestBody MergeFileDTO mergeFileDTO) {
  84. LoginUser user = SpringWebUtils.requireLogin();
  85. fileService.mergeFile(mergeFileDTO);
  86. FileUploadDTO uploadDTO = new FileUploadDTO();
  87. BeanCopy.from(mergeFileDTO).to(uploadDTO).copy();
  88. fileService.speedUpload(user.getId(), uploadDTO);
  89. log.info("用户[{}], 合并[{}]文件", user.getUsername(), uploadDTO.getIdentifier());
  90. return ResponseEntity.ok().build();
  91. }
  92. }

  1. package io.ddisk.controller;
  2. import io.ddisk.domain.dto.RegisterDTO;
  3. import io.ddisk.domain.vo.LoginUser;
  4. import io.ddisk.domain.vo.UserStorageVO;
  5. import io.ddisk.service.UserService;
  6. import io.ddisk.service.UserStorageService;
  7. import io.ddisk.utils.SpringWebUtils;
  8. import io.swagger.v3.oas.annotations.Operation;
  9. import io.swagger.v3.oas.annotations.Parameter;
  10. import io.swagger.v3.oas.annotations.Parameters;
  11. import io.swagger.v3.oas.annotations.tags.Tag;
  12. import org.hibernate.validator.constraints.Length;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.http.ResponseEntity;
  15. import org.springframework.validation.annotation.Validated;
  16. import org.springframework.web.bind.annotation.*;
  17. import javax.validation.constraints.Email;
  18. import javax.validation.constraints.NotBlank;
  19. /**
  20. * 用户的登录,注销交由spring security处理
  21. *
  22. */
  23. @Tag(name = "User", description = "该接口为用户接口,主要做用户登录,注册和校验token")
  24. @RequestMapping("user")
  25. @Validated
  26. @RestController
  27. public class UserController {
  28. @Autowired
  29. private UserService userService;
  30. @Autowired
  31. private UserStorageService userStorageService;
  32. @Operation(summary = "用户注册, 步骤一", description = "获取注册令牌,令牌发送至用户邮箱", tags = {"user"})
  33. @GetMapping(value = "register")
  34. @Parameters({
  35. @Parameter(name = "email", description = "用户邮箱", required = true)
  36. })
  37. public ResponseEntity<Void> sendRegisterToken(@Email String email) {
  38. userService.sendEmailToRegister(email);
  39. return ResponseEntity.ok().build();
  40. }
  41. @Operation(summary = "用户注册, 步骤二", description = "注册账号", tags = {"user"})
  42. @PostMapping(value = "register")
  43. public ResponseEntity<Void> registerUser(@Validated @RequestBody RegisterDTO registerDTO) {
  44. userService.addUser(registerDTO);
  45. return ResponseEntity.ok().build();
  46. }
  47. @Operation(summary = "设置头像", description = "设置用户头像", tags = {"user"})
  48. @PostMapping(value = "avatar")
  49. @Parameters({
  50. @Parameter(name = "fileId", description = "用户文件id", required = true)
  51. })
  52. public ResponseEntity<Void> setAvator(@NotBlank @Length(min = 32, max = 32) String fileId) {
  53. LoginUser user = SpringWebUtils.requireLogin();
  54. userService.setAvator(user.getId(), fileId);
  55. user.setImgUrl(fileId);
  56. return ResponseEntity.ok().build();
  57. }
  58. @Operation(summary = "获取用户信息", description = "获取用户信息", tags = {"user"})
  59. @GetMapping(value = "info")
  60. public ResponseEntity<LoginUser> getLoginUser() {
  61. return ResponseEntity.ok().body(SpringWebUtils.requireLogin());
  62. }
  63. @Operation(summary = "校验用户名", description = "检查用户是否已被注册", tags = {"user"})
  64. @GetMapping(value = "exist/username")
  65. @Parameters({
  66. @Parameter(name = "username", description = "用户名", required = true)
  67. })
  68. public ResponseEntity<Void> existUsername(
  69. @Length(min = 4, max = 16, message = "用户名长度必须在7-20位") String username) {
  70. userService.notExistUsername(username);
  71. return ResponseEntity.ok().build();
  72. }
  73. @Operation(summary = "校验邮箱", description = "检查邮箱是否已被使用", tags = {"user"})
  74. @GetMapping(value = "exist/email")
  75. @Parameters({
  76. @Parameter(name = "email", description = "用户邮箱", required = true)
  77. })
  78. public ResponseEntity<LoginUser> existEmail(@Email @NotBlank String email) {
  79. userService.notExistUsername(email);
  80. return ResponseEntity.ok().build();
  81. }
  82. @Operation(summary = "忘记密码,步骤1", description = "忘记密码之发送密码重置邮件", tags = {"user"})
  83. @GetMapping(value = "reset/passwd")
  84. @Parameters({
  85. @Parameter(name = "email", description = "用户邮箱", required = true)
  86. })
  87. public ResponseEntity<Void> forgetPasswd(@Email @NotBlank String email) {
  88. userService.sendEmailToResetPassword(email);
  89. return ResponseEntity.ok().build();
  90. }
  91. @Operation(summary = "忘记密码,步骤2", description = "忘记密码之重置密码", tags = {"user"})
  92. @PostMapping(value = "reset/passwd")
  93. @Parameters({
  94. @Parameter(name = "email", description = "用户邮箱", required = true),
  95. @Parameter(name = "password", description = "新密码", required = true),
  96. @Parameter(name = "token", description = "令牌,从邮件中获取", required = true)
  97. })
  98. public ResponseEntity<Void> regeneratePasswd(
  99. @Email @NotBlank String email,
  100. @Length(min = 7, max = 20, message = "密码长度必须在7-20位") String password,
  101. @Length(min = 36, max = 36, message = "密码长度必须在7-20位") String token) {
  102. userService.forgetPassword(email, password, token);
  103. return ResponseEntity.ok().build();
  104. }
  105. @Operation(summary = "修改密码", description = "修改密码", tags = {"user"})
  106. @Parameters({
  107. @Parameter(name = "oldPassword", description = "原密码", required = true),
  108. @Parameter(name = "newPassword", description = "新密码", required = true)
  109. })
  110. @GetMapping(value = "passwd")
  111. public ResponseEntity<Void> passwd(
  112. @Length(min = 7, max = 20, message = "密码长度必须在7-20位") String oldPassword,
  113. @Length(min = 7, max = 20, message = "密码长度必须在7-20位") String newPassword
  114. ) {
  115. LoginUser user = SpringWebUtils.requireLogin();
  116. userService.passwd(user.getId(), oldPassword, newPassword);
  117. return ResponseEntity.ok().build();
  118. }
  119. @Operation(summary = "用户内存使用", description = "获取用户磁盘信息,已使用和未使用大小", tags = {"user"})
  120. @GetMapping(value = "storage/info")
  121. public ResponseEntity<UserStorageVO> getStorageInfo() {
  122. UserStorageVO vo = userStorageService.getStorageInfo(SpringWebUtils.requireLogin());
  123. return ResponseEntity.ok().body(vo);
  124. }
  125. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/572948
推荐阅读
相关标签
  

闽ICP备14008679号