0


基于Springboot + vue的云盘系统

目录

一. 🦁 前言

本项目是在B站学习的项目改造而来,主要是一个模仿百度网盘的上传文件、下载文件功能以及网盘分享文件功能,希望你喜欢。

本系统是一个文件存储和共享平台,提供了强大的功能和可靠的数据保护,方便用户随时随地进行文件的管理和分享。本系统基于

Springboot+Vue

实现,操作简便,界面美观,拥有良好的用户体验和稳定的性能。无论是个人用户还是团队合作,都能够在此享受到高效和便捷的文件存储和共享服务。

二. 🦁 主要技术栈

  1. 后端SpringBootMySQLMybatisSpringMVCRedisffmpeg
  2. 前端Vue3Element-Plus

三. 🦁 架构搭建

tips:
该项目的项目结构改编参考了天罡大佬的《Maven 三层项目结构搭建》一文(天罡大佬人很好,很热心解答狮子疑惑的问题,

推荐关注哦

!!!),但是又有写不同的地方,狮子根据自己的理解整理成如下结构:

image-20230428112738573

1. 项目搭建效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 各部分作用

  • 表现层: web层,提供controller,处理http请求,提供给前端的API;
  • 业务逻辑层: service层,和业务相关,主要处理业务逻辑;
  • 数据访问层: dal层,做数据访问,主要使用Mybatis与MySQL交互数据;
  • 通用层:common层,主要存放实体类,常量,工具,异常类等。

四. 🦁 主要功能

1.功能图

云盘系统

2. 主要功能

2.1 分片上传文件

这个方法是本系统的核心功能,前端将文件分片后将参数传回,后台接收上传文件的参数,将文件暂存在临时目录中。如果是第一个分片,则判断是否存在相同的文件(根据文件的 MD5 值判断),如果存在相同的文件,则将其直接作为秒传处理,否则继续将文件保存在临时目录中。如果是最后一个分片,则将其记录在数据库中,并异步调用文件合并的方法。在整个上传过程中,还需要进行磁盘空间和用户可用空间的判断。最后返回上传结果。

@Transactional(rollbackFor =Exception.class)publicUploadResultDtouploadFile(SessionWebUserDto webUserDto,String fileId,MultipartFile file,String fileName,String filePid,String fileMd5,Integer chunkIndex,Integer chunks){File tempFileFolder =null;Boolean uploadSuccess =true;try{UploadResultDto resultDto =newUploadResultDto();if(StringTools.isEmpty(fileId)){
                fileId =StringTools.getRandomString(Constants.LENGTH_10);}
            resultDto.setFileId(fileId);Date curDate =newDate();UserSpaceDto spaceDto = redisComponent.getUserSpaceUse(webUserDto.getUserId());if(chunkIndex ==0){FileInfoQuery infoQuery =newFileInfoQuery();
                infoQuery.setFileMd5(fileMd5);
                infoQuery.setSimplePage(newSimplePage(0,1));
                infoQuery.setStatus(FileStatusEnums.USING.getStatus());List<FileInfo> dbFileList =this.fileInfoMapper.selectList(infoQuery);//秒传if(!dbFileList.isEmpty()){FileInfo dbFile = dbFileList.get(0);//判断文件状态if(dbFile.getFileSize()+ spaceDto.getUseSpace()> spaceDto.getTotalSpace()){thrownewBusinessException(ResponseCodeEnum.CODE_904);}
                    dbFile.setFileId(fileId);
                    dbFile.setFilePid(filePid);
                    dbFile.setUserId(webUserDto.getUserId());
                    dbFile.setFileMd5(null);
                    dbFile.setCreateTime(curDate);
                    dbFile.setLastUpdateTime(curDate);
                    dbFile.setStatus(FileStatusEnums.USING.getStatus());
                    dbFile.setDelFlag(FileDelFlagEnums.USING.getFlag());
                    dbFile.setFileMd5(fileMd5);
                    fileName =autoRename(filePid, webUserDto.getUserId(), fileName);
                    dbFile.setFileName(fileName);this.fileInfoMapper.insert(dbFile);
                    resultDto.setStatus(UploadStatusEnums.UPLOAD_SECONDS.getCode());//更新用户空间使用updateUserSpace(webUserDto, dbFile.getFileSize());return resultDto;}}//暂存在临时目录String tempFolderName = appConfig.getProjectFolder()+Constants.FILE_FOLDER_TEMP;String currentUserFolderName = webUserDto.getUserId()+ fileId;//创建临时目录
            tempFileFolder =newFile(tempFolderName + currentUserFolderName);if(!tempFileFolder.exists()){
                tempFileFolder.mkdirs();}//判断磁盘空间Long currentTempSize = redisComponent.getFileTempSize(webUserDto.getUserId(), fileId);if(file.getSize()+ currentTempSize + spaceDto.getUseSpace()> spaceDto.getTotalSpace()){thrownewBusinessException(ResponseCodeEnum.CODE_904);}File newFile =newFile(tempFileFolder.getPath()+"/"+ chunkIndex);
            file.transferTo(newFile);//保存临时大小
            redisComponent.saveFileTempSize(webUserDto.getUserId(), fileId, file.getSize());//不是最后一个分片,直接返回if(chunkIndex < chunks -1){
                resultDto.setStatus(UploadStatusEnums.UPLOADING.getCode());return resultDto;}
            redisComponent.saveFileTempSize(webUserDto.getUserId(), fileId, file.getSize());//最后一个分片上传完成,记录数据库,异步合并分片String month =DateUtil.format(curDate,DateTimePatternEnum.YYYYMM.getPattern());String fileSuffix =StringTools.getFileSuffix(fileName);//真实文件名String realFileName = currentUserFolderName + fileSuffix;FileTypeEnums fileTypeEnum =FileTypeEnums.getFileTypeBySuffix(fileSuffix);//自动重命名
            fileName =autoRename(filePid, webUserDto.getUserId(), fileName);FileInfo fileInfo =newFileInfo();
            fileInfo.setFileId(fileId);
            fileInfo.setUserId(webUserDto.getUserId());
            fileInfo.setFileMd5(fileMd5);
            fileInfo.setFileName(fileName);
            fileInfo.setFilePath(month +"/"+ realFileName);
            fileInfo.setFilePid(filePid);
            fileInfo.setCreateTime(curDate);
            fileInfo.setLastUpdateTime(curDate);
            fileInfo.setFileCategory(fileTypeEnum.getCategory().getCategory());
            fileInfo.setFileType(fileTypeEnum.getType());
            fileInfo.setStatus(FileStatusEnums.TRANSFER.getStatus());
            fileInfo.setFolderType(FileFolderTypeEnums.FILE.getType());
            fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());this.fileInfoMapper.insert(fileInfo);Long totalSize = redisComponent.getFileTempSize(webUserDto.getUserId(), fileId);updateUserSpace(webUserDto, totalSize);

            resultDto.setStatus(UploadStatusEnums.UPLOAD_FINISH.getCode());//事务提交后调用异步方法TransactionSynchronizationManager.registerSynchronization(newTransactionSynchronization(){@OverridepublicvoidafterCommit(){
                    fileInfoService.transferFile(fileInfo.getFileId(), webUserDto);}});return resultDto;}catch(BusinessException e){
            uploadSuccess =false;
            logger.error("文件上传失败", e);throw e;}catch(Exception e){
            uploadSuccess =false;
            logger.error("文件上传失败", e);thrownewBusinessException("文件上传失败");}finally{//如果上传失败,清除临时目录if(tempFileFolder !=null&&!uploadSuccess){try{FileUtils.deleteDirectory(tempFileFolder);}catch(IOException e){
                    logger.error("删除临时目录失败");}}}}

2.2 存储分享记录

这个方法用于存储分享记录,方法签名为public void saveShare(FileShare share)。方法的输入参数为一个FileShare对象。

在方法内部,首先根据share对象中的validType属性获取对应的ShareValidTypeEnums枚举值,如果无法获取该枚举值,则抛出BusinessException异常并返回错误码ResponseCodeEnum.CODE_600。

接着,根据validType属性判断分享是否永久有效,如果不是,则设置该分享的过期时间为当前时间加上对应的天数。

然后,获取当前时间作为分享时间,并为分享记录设置随机的分享ID和提取码(如果提取码为空)。

最后,将分享记录保存至数据库中。

@OverridepublicvoidsaveShare(FileShare share){ShareValidTypeEnums typeEnum =ShareValidTypeEnums.getByType(share.getValidType());if(null== typeEnum){thrownewBusinessException(ResponseCodeEnum.CODE_600);}if(typeEnum !=ShareValidTypeEnums.FOREVER){
            share.setExpireTime(DateUtil.getAfterDate(typeEnum.getDays()));}Date curDate =newDate();
        share.setShareTime(curDate);if(StringTools.isEmpty(share.getCode())){
            share.setCode(StringTools.getRandomString(Constants.LENGTH_5));}
        share.setShareId(StringTools.getRandomString(Constants.LENGTH_20));this.fileShareMapper.insert(share);}

五. 🦁 效果显示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

标签: spring boot vue.js java

本文转载自: https://blog.csdn.net/m0_58847451/article/details/130863590
版权归原作者 狮子也疯狂 所有, 如有侵权,请联系我们删除。

“基于Springboot + vue的云盘系统”的评论:

还没有评论