为何需要用到递归?
在网盘系统中,文件的类型分为文件和文件夹两种类型。当我们想要批量删除文件时,不乏其中会包含文件夹,而想要删除这个文件夹,自然其中所包含的文件都要删除,而其中所包含的文件也有可能是文件夹,所以需要用到递归。
代码实现(Service层)
/*** 删除文件到回收站* @param fileIds* @param userId*/@Overridepublic void removeFileToRecycleBin(String fileIds, String userId) {String[] fileIdArray = fileIds.split(",");LambdaQueryWrapper<FileInfo> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(FileInfo::getUserId, userId).in(FileInfo::getFileId, Arrays.asList(fileIdArray)).eq(FileInfo::getDelFlag, FileDelFlagEnums.USING.getFlag());List<FileInfo> fileInfoList = this.baseMapper.selectList(queryWrapper);if(fileInfoList.isEmpty()){return;}List<String> delFilePidList = new ArrayList<>();for (FileInfo fileInfo : fileInfoList) {findAllSubFolderList(delFilePidList, userId, fileInfo.getFileId(), FileDelFlagEnums.USING.getFlag());}if(!delFilePidList.isEmpty()){// 将这些目录下的所有文件标记为“已删除”LambdaUpdateWrapper<FileInfo> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.eq(FileInfo::getUserId, userId).in(FileInfo::getFilePid, delFilePidList).eq(FileInfo::getDelFlag, FileDelFlagEnums.USING.getFlag());FileInfo updateFileInfo = new FileInfo();updateFileInfo.setDelFlag(FileDelFlagEnums.DEL.getFlag());this.baseMapper.update(updateFileInfo, updateWrapper);}// 将选中的文件标记为“回收站”List<String> delFileIdList = Arrays.asList(fileIdArray);LambdaUpdateWrapper<FileInfo> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.eq(FileInfo::getUserId, userId).in(FileInfo::getFileId, delFileIdList);FileInfo updateFileInfo = new FileInfo();updateFileInfo.setDelFlag(FileDelFlagEnums.RECYCLE.getFlag());updateFileInfo.setRecoveryTime(new Date());this.baseMapper.update(updateFileInfo, updateWrapper);}
文件的DelFlag类型有三种,正常、回收站、删除。只有选中的文件会被标记为“回收站”,而选中的文件夹内包含的文件则是标记为“已删除”。
为什么要这么设计呢?
可以参考我们windows的回收站,当我们把一个文件夹扔进回收站后,会发现在回收站中是不能把这个文件夹打开,自然也就无法看到文件夹中的文件了,所以文件夹中的文件就不需要标记为"回收站",直接标记为“已删除”。当我们需要去恢复时,只需要将那些父id为这个文件夹的文件重新标记为"正常"即可。
上述代码中用到的"findAllSubFolderList"就是递归查找目标目录下的所有目录的方法,让我们看看实现的代码:
/*** 递归查找目标目录下的所有目录* @param fileIdList* @param userId* @param fileId* @param delFlag*/private void findAllSubFolderList(List<String> fileIdList, String userId, String fileId, Integer delFlag){fileIdList.add(fileId);LambdaQueryWrapper<FileInfo> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(FileInfo::getUserId, userId).eq(FileInfo::getFilePid, fileId).eq(FileInfo::getDelFlag, delFlag).eq(FileInfo::getFolderType, FileFolderTypeEnums.FOLDER.getType());// 找到这个目录的所有子目录List<FileInfo> fileInfoList = this.baseMapper.selectList(queryWrapper);// 递归查找所有子目录下的所有文件for (FileInfo fileInfo : fileInfoList) {findAllSubFolderList(fileIdList, userId, fileInfo.getFileId(), delFlag);}}