第2-3-7章 个人网盘服务接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss
目录
- 第2-1-2章 传统方式安装FastDFS-附FastDFS常用命令
第2-1-3章 docker-compose安装FastDFS,实现文件存储服务
第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料全套代码及资料全部完整提供,点此处下载
5.8.1 接口导入-分页查询附件
接口文档:
AttachmentController代码:
/** * 分页查询附件 * */ @ApiOperation(value = "分页查询附件", notes = "分页查询附件") @ApiImplicitParams({ @ApiImplicitParam(name = "current", value = "当前页", dataType = "long", paramType = "query", defaultValue = "1"), @ApiImplicitParam(name = "size", value = "每页显示几条", dataType = "long", paramType = "query", defaultValue = "10"), }) @GetMapping(value = "/page") public R
> page(FilePageReqDTO data) { Page page = getPage(); attachmentService.page(page, data); return success(page); } AttachmentService接口:
/** * 查询附件分页数据 * * @param page * @param data * @return */ IPage
page(Page page, FilePageReqDTO data); AttachmentServiceImpl类:
/** * 查询附件分页数据 * * @param page * @param data * @return */ public IPage
page(Page page, FilePageReqDTO data) { Attachment attachment = dozer.map(data, Attachment.class); // ${ew.customSqlSegment} 语法一定要手动eq like 等 不能用lbQ! LbqWrapper wrapper = Wraps. lbQ() .like(Attachment::getSubmittedFileName, attachment.getSubmittedFileName()) .like(Attachment::getBizType, attachment.getBizType()) .like(Attachment::getBizId, attachment.getBizId()) .eq(Attachment::getDataType, attachment.getDataType()) .orderByDesc(Attachment::getId); return baseMapper.page(page, wrapper); } 5.8.2 接口导入-根据业务类型/业务id查询附件
接口文档:
AttachmentController代码:
@ApiOperation(value = "查询附件", notes = "查询附件") @ApiResponses( @ApiResponse(code = 60103, message = "文件id为空") ) @GetMapping public R
- > findAttachment(@RequestParam(value = "bizTypes", required = false) String[] bizTypes,
@RequestParam(value = "bizIds", required = false) String[] bizIds) {
//不能同时为空
BizAssert.isTrue(!(ArrayUtils.isEmpty(bizTypes) && ArrayUtils.isEmpty(bizIds)), BASE_VALID_PARAM.build("业务类型不能为空"));
return success(attachmentService.find(bizTypes, bizIds));
}
AttachmentService接口:
/** * 根据业务类型和业务id查询附件 * * @param bizTypes * @param bizIds * @return */ List
find(String[] bizTypes, String[] bizIds); AttachmentServiceImpl类:
/** * 根据业务类型和业务id查询附件 * * @param bizTypes * @param bizIds * @return */ public List
find(String[] bizTypes, String[] bizIds) { return baseMapper.find(bizTypes, bizIds); } 5.9 导入网盘服务接口
前面我们已经完成了文件服务中的附件服务相关接口的开发,附件服务最终是将上传的文件信息保存在pd_attachment表中。
本小节要完成的是文件服务中的网盘服务功能,此功能最终是将上传的文件信息保存在pd_file表中。网盘服务和附件服务非常类似,只是多了一个文件夹的概念。
5.9.1 导入FileController
package com.itheima.pinda.file.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.itheima.pinda.base.BaseController; import com.itheima.pinda.base.R; import com.itheima.pinda.dozer.DozerUtils; import com.itheima.pinda.file.dto.FilePageReqDTO; import com.itheima.pinda.file.dto.FileUpdateDTO; import com.itheima.pinda.file.dto.FolderDTO; import com.itheima.pinda.file.dto.FolderSaveDTO; import com.itheima.pinda.file.entity.File; import com.itheima.pinda.file.manager.FileRestManager; import com.itheima.pinda.file.service.FileService; import com.itheima.pinda.log.annotation.SysLog; import io.swagger.annotations.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import javax.validation.constraints.NotNull; /** * 文件前端控制器 */ @Validated @RestController @RequestMapping("/file") @Slf4j @Api(value = "文件表", tags = "文件表") public class FileController extends BaseController { @Autowired private FileService fileService; @Autowired private FileRestManager fileRestManager; @Autowired private DozerUtils dozerUtils; /** * 查询单个文件信息 * * @param id * @return */ @ApiOperation(value = "查询文件", notes = "查询文件") @GetMapping public R
get(@RequestParam(value = "id") Long id) { File file = fileService.getById(id); if (file != null && file.getIsDelete()) { return success(null); } return success(file); } /** * 获取文件分页 */ @ApiOperation(value = "分页查询文件", notes = "获取文件分页") @ApiImplicitParams({ @ApiImplicitParam(name = "current", value = "当前页", dataType = "long", paramType = "query", defaultValue = "1"), @ApiImplicitParam(name = "size", value = "每页显示几条", dataType = "long", paramType = "query", defaultValue = "10"), }) @GetMapping(value = "/page") public R > page(FilePageReqDTO data) { return success(fileRestManager.page(getPage(), data)); } /** * 上传文件 */ @ApiOperation(value = "上传文件", notes = "上传文件 ") @ApiResponses({ @ApiResponse(code = 60102, message = "文件夹为空"), }) @ApiImplicitParams({ @ApiImplicitParam(name = "source", value = "文件来源", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "userId", value = "用户id", dataType = "long", paramType = "query"), @ApiImplicitParam(name = "folderId", value = "文件夹id", dataType = "long", paramType = "query"), @ApiImplicitParam(name = "file", value = "附件", dataType = "MultipartFile", allowMultiple = true, required = true), }) @RequestMapping(value = "/upload", method = RequestMethod.POST) public R upload( @NotNull(message = "文件夹不能为空") @RequestParam(name = "source", defaultValue = "inner") String source, @RequestParam(name = "userId", required = false) Long userId, @RequestParam(value = "folderId") Long folderId, @RequestParam(value = "file") MultipartFile simpleFile) { //1,先将文件存在本地,并且生成文件名 log.info("contentType={}, name={} , sfname={}", simpleFile.getContentType(), simpleFile.getName(), simpleFile.getOriginalFilename()); // 忽略路径字段,只处理文件类型 if (simpleFile.getContentType() == null) { return fail("文件为空"); } File file = fileService.upload(simpleFile, folderId, source, userId); return success(file); } /** * 保存文件夹 */ @ApiResponses({ @ApiResponse(code = 60000, message = "文件夹为空"), @ApiResponse(code = 60001, message = "文件夹名称为空"), @ApiResponse(code = 60002, message = "父文件夹为空"), }) @ApiOperation(value = "新增文件夹", notes = "新增文件夹") @RequestMapping(value = "", method = RequestMethod.POST) public R saveFolder(@Valid @RequestBody FolderSaveDTO folderSaveDto) { //2,获取身份 FolderDTO folder = fileService.saveFolder(folderSaveDto); return success(folder); } /** * 修改文件、文件夹信息 * * @param fileUpdateDTO * @return */ @ApiOperation(value = "修改文件/文件夹名称", notes = "修改文件/文件夹名称") @ApiResponses({ @ApiResponse(code = 60100, message = "文件为空"), }) @RequestMapping(value = "", method = RequestMethod.PUT) public R update(@Valid @RequestBody FileUpdateDTO fileUpdateDTO) { // 判断文件名是否有 后缀 if (StringUtils.isNotEmpty(fileUpdateDTO.getSubmittedFileName())) { File oldFile = fileService.getById(fileUpdateDTO.getId()); if (oldFile.getExt() != null && !fileUpdateDTO.getSubmittedFileName().endsWith(oldFile.getExt())) { fileUpdateDTO.setSubmittedFileName(fileUpdateDTO.getSubmittedFileName() + "." + oldFile.getExt()); } } File file = dozerUtils.map2(fileUpdateDTO, File.class); fileService.updateById(file); return success(true); } /** * 根据Ids进行文件删除 * * @param ids * @return */ @ApiOperation(value = "根据Ids进行文件删除", notes = "根据Ids进行文件删除 ") @DeleteMapping(value = "/ids") public R removeList(@RequestParam(value = "ids[]") Long[] ids) { Long userId = getUserId(); return success(fileService.removeList(userId, ids)); } /** * 下载一个文件或多个文件打包下载 * * @param ids * @param response * @throws Exception */ @ApiOperation(value = "下载一个文件或多个文件打包下载", notes = "下载一个文件或多个文件打包下载") @GetMapping(value = "/download", produces = "application/octet-stream") public void download( @ApiParam(name = "ids[]", value = "文件id 数组") @RequestParam(value = "ids[]") Long[] ids, HttpServletRequest request, HttpServletResponse response) throws Exception { fileRestManager.download(request, response, ids, null); } } 5.9.2 导入StatisticsController
package com.itheima.pinda.file.controller; import com.itheima.pinda.base.BaseController; import com.itheima.pinda.base.R; import com.itheima.pinda.file.domain.FileStatisticsDO; import com.itheima.pinda.file.dto.FileOverviewDTO; import com.itheima.pinda.file.dto.FileStatisticsAllDTO; import com.itheima.pinda.file.service.FileService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.time.LocalDateTime; import java.util.List; /** * 文件统计接口 */ @Slf4j @RestController @RequestMapping("/statistics") @Api(value = "Statistics", tags = "统计接口") public class StatisticsController extends BaseController { @Autowired private FileService fileService; @ApiOperation(value = "云盘首页数据概览", notes = "云盘首页数据概览") @GetMapping(value = "/overview") public R
overview(@RequestParam(name = "userId", required = false) Long userId) { return success(fileService.findOverview(userId, null, null)); } @ApiOperation(value = "按照类型,统计各种类型的 大小和数量", notes = "按照类型,统计当前登录人各种类型的大小和数量") @GetMapping(value = "/type") public R - > findAllByDataType(@RequestParam(name = "userId", required = false) Long userId) {
return success(fileService.findAllByDataType(userId));
}
@ApiOperation(value = "按照时间统计各种类型的文件的数量和大小", notes = "按照时间统计各种类型的文件的数量和大小 不指定时间,默认查询一个月")
@GetMapping(value = "")
public R
findNumAndSizeToTypeByDate(@RequestParam(name = "userId", required = false) Long userId, @RequestParam(value = "startTime", required = false) LocalDateTime startTime, @RequestParam(value = "endTime", required = false) LocalDateTime endTime) { return success(fileService.findNumAndSizeToTypeByDate(userId, startTime, endTime)); } } 5.9.3 导入FileRestManager
package com.itheima.pinda.file.manager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.itheima.pinda.context.BaseContextHandler; import com.itheima.pinda.file.constant.FileConstants; import com.itheima.pinda.file.dto.FilePageReqDTO; import com.itheima.pinda.file.entity.File; import com.itheima.pinda.file.service.FileService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import static com.itheima.pinda.utils.StrPool.DEF_PARENT_ID; /** * 文件 公共代码 管理类 */ @Component public class FileRestManager { @Autowired private FileService fileService; public IPage
page(IPage page, FilePageReqDTO filePageReq) { //类型和文件夹id同时为null时, 表示查询 全部文件 if (filePageReq.getFolderId() == null && filePageReq.getDataType() == null) { filePageReq.setFolderId(DEF_PARENT_ID); } QueryWrapper query = new QueryWrapper<>(); LambdaQueryWrapper lambdaQuery = query.lambda() .eq(File::getIsDelete, false) .eq(filePageReq.getDataType() != null, File::getDataType, filePageReq.getDataType()) .eq(filePageReq.getFolderId() != null, File::getFolderId, filePageReq.getFolderId()) .like(StringUtils.isNotEmpty(filePageReq.getSubmittedFileName()), File::getSubmittedFileName, filePageReq.getSubmittedFileName()); query.orderByDesc(String.format("case when %s='DIR' THEN 1 else 0 end", FileConstants.DATA_TYPE)); lambdaQuery.orderByDesc(File::getCreateTime); fileService.page(page, lambdaQuery); return page; } public void download(HttpServletRequest request, HttpServletResponse response, Long[] ids, Long userId) throws Exception { userId = userId == null || userId <= 0 ? BaseContextHandler.getUserId() : userId; fileService.download(request, response, ids, userId); } } 5.9.4 导入FileService
package com.itheima.pinda.file.service; import com.baomidou.mybatisplus.extension.service.IService; import com.itheima.pinda.file.domain.FileAttrDO; import com.itheima.pinda.file.domain.FileStatisticsDO; import com.itheima.pinda.file.dto.FileOverviewDTO; import com.itheima.pinda.file.dto.FileStatisticsAllDTO; import com.itheima.pinda.file.dto.FolderDTO; import com.itheima.pinda.file.dto.FolderSaveDTO; import com.itheima.pinda.file.entity.File; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.time.LocalDateTime; import java.util.List; /** * 业务接口 * 文件表 * */ public interface FileService extends IService
{ /** * 保存文件夹 * * @param folderSaveDto 文件夹 * @return */ FolderDTO saveFolder(FolderSaveDTO folderSaveDto); /** * 根据文件id下载文件,并统计下载次数 * * @param request 请求 * @param response 响应 * @param ids 文件id集合 * @param userId 用户id * @throws Exception */ void download(HttpServletRequest request, HttpServletResponse response, Long[] ids, Long userId) throws Exception; /** * 根据文件id和用户id 删除文件或者文件夹 * * @param userId 用户id * @param ids 文件id集合 * @return */ Boolean removeList(Long userId, Long[] ids); /** * 根据文件夹id查询 * * @param folderId * @return */ FileAttrDO getFileAttrDo(Long folderId); /** * 文件上传 * * @param simpleFile 文件 * @param folderId 文件夹id * @return */ File upload(MultipartFile simpleFile, Long folderId); /** * 文件上传 * * @param simpleFile * @param folderId * @param source * @param userId * @return */ File upload(MultipartFile simpleFile, Long folderId, String source, Long userId); /** * 首页概览 * * @param userId * @param startTime * @param endTime * @return */ FileOverviewDTO findOverview(Long userId, LocalDateTime startTime, LocalDateTime endTime); /** * 首页个人文件发展概览 * * @param userId * @param startTime * @param endTime * @return */ FileStatisticsAllDTO findAllByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime); /** * 按照 数据类型分类查询 当前人的所有文件的数量和大小 * * @param userId * @return */ List findAllByDataType(Long userId); /** * 查询下载排行前20的文件 * * @param userId * @return */ List downTop20(Long userId); /** * 根据日期查询,特定类型的数量和大小 * * @param userId * @param startTime * @param endTime * @return */ FileStatisticsAllDTO findNumAndSizeToTypeByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime); /** * 根据日期查询下载大小 * * @param userId * @param startTime * @param endTime * @return */ FileStatisticsAllDTO findDownSizeByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime); } 5.9.5 导入FileServiceImpl
package com.itheima.pinda.file.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.itheima.pinda.database.mybatis.conditions.Wraps; import com.itheima.pinda.database.mybatis.conditions.update.LbuWrapper; import com.itheima.pinda.dozer.DozerUtils; import com.itheima.pinda.file.biz.FileBiz; import com.itheima.pinda.file.dao.FileMapper; import com.itheima.pinda.file.domain.FileAttrDO; import com.itheima.pinda.file.domain.FileDO; import com.itheima.pinda.file.domain.FileDeleteDO; import com.itheima.pinda.file.domain.FileStatisticsDO; import com.itheima.pinda.file.dto.FileOverviewDTO; import com.itheima.pinda.file.dto.FileStatisticsAllDTO; import com.itheima.pinda.file.dto.FolderDTO; import com.itheima.pinda.file.dto.FolderSaveDTO; import com.itheima.pinda.file.entity.File; import com.itheima.pinda.file.enumeration.DataType; import com.itheima.pinda.file.enumeration.IconType; import com.itheima.pinda.file.service.FileService; import com.itheima.pinda.file.strategy.FileStrategy; import com.itheima.pinda.utils.BizAssert; import com.itheima.pinda.utils.DateUtils; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import static com.itheima.pinda.exception.code.ExceptionCode.BASE_VALID_PARAM; import static com.itheima.pinda.utils.StrPool.DEF_PARENT_ID; import static com.itheima.pinda.utils.StrPool.DEF_ROOT_PATH; import static java.util.stream.Collectors.groupingBy; /** * 业务实现类 * 文件表 */ @Slf4j @Service public class FileServiceImpl extends ServiceImpl
implements FileService { @Autowired private DozerUtils dozerUtils; @Autowired private FileBiz fileBiz; @Resource private FileStrategy fileStrategy; @Override public File upload(MultipartFile simpleFile, Long folderId) { FileAttrDO fileAttrDO = this.getFileAttrDo(folderId); String treePath = fileAttrDO.getTreePath(); String folderName = fileAttrDO.getFolderName(); Integer grade = fileAttrDO.getGrade(); File file = fileStrategy.upload(simpleFile); file.setFolderId(folderId); file.setFolderName(folderName); file.setGrade(grade); file.setTreePath(treePath); super.save(file); return file; } @Override public File upload(MultipartFile simpleFile, Long folderId, String source, Long userId) { FileAttrDO fileAttrDO = this.getFileAttrDo(folderId); String treePath = fileAttrDO.getTreePath(); String folderName = fileAttrDO.getFolderName(); Integer grade = fileAttrDO.getGrade(); File file = fileStrategy.upload(simpleFile); file.setFolderId(folderId); file.setFolderName(folderName); file.setGrade(grade); file.setTreePath(treePath); file.setSource(source); if (userId != null) { file.setCreateUser(userId); } super.save(file); return file; } @Override public FileAttrDO getFileAttrDo(Long folderId) { String treePath = DEF_ROOT_PATH; String folderName = ""; Integer grade = 1; if (folderId == null || folderId <= 0) { return new FileAttrDO(treePath, grade, folderName, DEF_PARENT_ID); } File folder = this.getById(folderId); if (folder != null && !folder.getIsDelete() && DataType.DIR.eq(folder.getDataType())) { folderName = folder.getSubmittedFileName(); treePath = StringUtils.join(folder.getTreePath(), folder.getId(), DEF_ROOT_PATH); grade = folder.getGrade() + 1; } BizAssert.isTrue(grade <= 10, BASE_VALID_PARAM.build("文件夹层级不能超过10层")); return new FileAttrDO(treePath, grade, folderName, folderId); } @Override public FolderDTO saveFolder(FolderSaveDTO folderSaveDto) { File folder = dozerUtils.map2(folderSaveDto, File.class); if (folderSaveDto.getFolderId() == null || folderSaveDto.getFolderId() <= 0) { folder.setFolderId(DEF_PARENT_ID); folder.setTreePath(DEF_ROOT_PATH); folder.setGrade(1); } else { File parent = super.getById(folderSaveDto.getFolderId()); BizAssert.notNull(parent, BASE_VALID_PARAM.build("父文件夹不能为空")); BizAssert.isFalse(parent.getIsDelete(), BASE_VALID_PARAM.build("父文件夹已经被删除")); BizAssert.equals(DataType.DIR.name(), parent.getDataType().name(), BASE_VALID_PARAM.build("父文件夹不存在")); BizAssert.isTrue(parent.getGrade() < 10, BASE_VALID_PARAM.build("文件夹层级不能超过10层")); folder.setFolderName(parent.getSubmittedFileName()); folder.setTreePath(StringUtils.join(parent.getTreePath(), parent.getId(), DEF_ROOT_PATH)); folder.setGrade(parent.getGrade() + 1); } if (folderSaveDto.getOrderNum() == null) { folderSaveDto.setOrderNum(0); } folder.setIsDelete(false); folder.setDataType(DataType.DIR); folder.setIcon(IconType.DIR.getIcon()); setDate(folder); super.save(folder); return dozerUtils.map2(folder, FolderDTO.class); } private void setDate(File file) { LocalDateTime now = LocalDateTime.now(); file.setCreateMonth(DateUtils.formatAsYearMonthEn(now)) .setCreateWeek(DateUtils.formatAsYearWeekEn(now)) .setCreateDay(DateUtils.formatAsDateEn(now)); } public boolean removeFile(Long[] ids, Long userId) { LbuWrapper lambdaUpdate = Wraps. lbU() .in(File::getId, ids) .eq(File::getCreateUser, userId); File file = File.builder().isDelete(Boolean.TRUE).build(); return super.update(file, lambdaUpdate); } @Override public Boolean removeList(Long userId, Long[] ids) { if (ArrayUtils.isEmpty(ids)) { return Boolean.TRUE; } List list = super.list(Wrappers. lambdaQuery().in(File::getId, ids)); if (list.isEmpty()) { return true; } super.removeByIds(Arrays.asList(ids)); fileStrategy.delete(list.stream().map((fi) -> FileDeleteDO.builder() .relativePath(fi.getRelativePath()) .fileName(fi.getFilename()) .group(fi.getGroup()) .path(fi.getPath()) .file(false) .build()) .collect(Collectors.toList())); return true; } @Override public void download(HttpServletRequest request, HttpServletResponse response, Long[] ids, Long userId) throws Exception { if (ids == null || ids.length == 0) { return; } List list = (List ) super.listByIds(Arrays.asList(ids)); if (list == null || list.size() == 0) { return; } List listDo = list.stream().map((file) -> FileDO.builder() .dataType(file.getDataType()) .size(file.getSize()) .submittedFileName(file.getSubmittedFileName()) .url(file.getUrl()) .build()) .collect(Collectors.toList()); fileBiz.down(listDo, request, response); } @Override public FileOverviewDTO findOverview(Long userId, LocalDateTime startTime, LocalDateTime endTime) { InnerQueryDate innerQueryDate = new InnerQueryDate(userId, startTime, endTime).invoke(); startTime = innerQueryDate.getStartTime(); endTime = innerQueryDate.getEndTime(); List list = baseMapper.findNumAndSizeByUserId(userId, null, "ALL", startTime, endTime); FileOverviewDTO.FileOverviewDTOBuilder builder = FileOverviewDTO.myBuilder(); long allSize = 0L; int allNum = 0; for (FileStatisticsDO fs : list) { allSize += fs.getSize(); allNum += fs.getNum(); switch (fs.getDataType()) { case DIR: builder.dirNum(fs.getNum()); break; case IMAGE: builder.imgNum(fs.getNum()); break; case VIDEO: builder.videoNum(fs.getNum()); break; case DOC: builder.docNum(fs.getNum()); break; case AUDIO: builder.audioNum(fs.getNum()); break; case OTHER: builder.otherNum(fs.getNum()); break; default: break; } } builder.allFileNum(allNum).allFileSize(allSize); return builder.build(); } @Override public FileStatisticsAllDTO findAllByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) { InnerQueryDate innerQueryDate = new InnerQueryDate(userId, startTime, endTime).invoke(); startTime = innerQueryDate.getStartTime(); endTime = innerQueryDate.getEndTime(); List dateList = innerQueryDate.getDateList(); String dateType = innerQueryDate.getDateType(); //不完整的数据 List list = baseMapper.findNumAndSizeByUserId(userId, dateType, null, startTime, endTime); //按月份分类 Map > map = list.stream().collect(groupingBy(FileStatisticsDO::getDateType)); List sizeList = new ArrayList<>(); List numList = new ArrayList<>(); dateList.forEach((date) -> { if (map.containsKey(date)) { List subList = map.get(date); Long size = subList.stream().mapToLong(FileStatisticsDO::getSize).sum(); Integer num = subList.stream().filter((fs) -> !DataType.DIR.eq(fs.getDataType())) .mapToInt(FileStatisticsDO::getNum).sum(); sizeList.add(size); numList.add(num); } else { sizeList.add(0L); numList.add(0); } }); return FileStatisticsAllDTO.builder().dateList(dateList).numList(numList).sizeList(sizeList).build(); } @Override public List findAllByDataType(Long userId) { List dataTypes = Arrays.asList(DataType.values()); List list = baseMapper.findNumAndSizeByUserId(userId, null, "ALL", null, null); Map > map = list.stream().collect(groupingBy(FileStatisticsDO::getDataType)); return dataTypes.stream().map((type) -> { FileStatisticsDO fs = null; if (map.containsKey(type)) { fs = map.get(type).get(0); } else { fs = FileStatisticsDO.builder().dataType(type).size(0L).num(0).build(); } return fs; }).collect(Collectors.toList()); } @Override public List downTop20(Long userId) { return baseMapper.findDownTop20(userId); } @Override public FileStatisticsAllDTO findNumAndSizeToTypeByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) { return common(userId, startTime, endTime, (qd) -> baseMapper.findNumAndSizeByUserId(qd.getUserId(), qd.getDateType(), "ALL", qd.getStartTime(), qd.getEndTime())); } @Override public FileStatisticsAllDTO findDownSizeByDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) { return common(userId, startTime, endTime, (qd) -> baseMapper.findDownSizeByDate(qd.getUserId(), qd.getDateType(), qd.getStartTime(), qd.getEndTime())); } /** * 抽取公共查询公共代码 * * @param userId 用户id * @param startTime 开始时间 * @param endTime 结束时间 * @param function 回调函数 * @return */ private FileStatisticsAllDTO common(Long userId, LocalDateTime startTime, LocalDateTime endTime, Function > function) { InnerQueryDate innerQueryDate = new InnerQueryDate(userId, startTime, endTime).invoke(); List dateList = innerQueryDate.getDateList(); List list = function.apply(innerQueryDate); //按月份分类 Map > map = list.stream().collect(groupingBy(FileStatisticsDO::getDateType)); List sizeList = new ArrayList<>(dateList.size()); List numList = new ArrayList<>(dateList.size()); List dirNumList = new ArrayList<>(dateList.size()); List imgSizeList = new ArrayList<>(dateList.size()); List imgNumList = new ArrayList<>(dateList.size()); List videoSizeList = new ArrayList<>(dateList.size()); List videoNumList = new ArrayList<>(dateList.size()); List audioSizeList = new ArrayList<>(dateList.size()); List audioNumList = new ArrayList<>(dateList.size()); List docSizeList = new ArrayList<>(dateList.size()); List docNumList = new ArrayList<>(dateList.size()); List otherSizeList = new ArrayList<>(dateList.size()); List otherNumList = new ArrayList<>(dateList.size()); dateList.forEach((date) -> { if (map.containsKey(date)) { List subList = map.get(date); Function > stream = (dataType) -> subList.stream().filter((fs) -> !dataType.eq(fs.getDataType())); Long size = stream.apply(DataType.DIR).mapToLong(FileStatisticsDO::getSize).sum(); Integer num = stream.apply(DataType.DIR).mapToInt(FileStatisticsDO::getNum).sum(); sizeList.add(size); numList.add(num); Integer dirNum = subList.stream().filter((fs) -> DataType.DIR.eq(fs.getDataType())) .mapToInt(FileStatisticsDO::getNum).sum(); dirNumList.add(dirNum); add(imgSizeList, imgNumList, subList, DataType.IMAGE); add(videoSizeList, videoNumList, subList, DataType.VIDEO); add(audioSizeList, audioNumList, subList, DataType.AUDIO); add(docSizeList, docNumList, subList, DataType.DOC); add(otherSizeList, otherNumList, subList, DataType.OTHER); } else { sizeList.add(0L); numList.add(0); dirNumList.add(0); imgSizeList.add(0L); imgNumList.add(0); videoSizeList.add(0L); videoNumList.add(0); audioSizeList.add(0L); audioNumList.add(0); docSizeList.add(0L); docNumList.add(0); otherSizeList.add(0L); otherNumList.add(0); } }); return FileStatisticsAllDTO.builder() .dateList(dateList) .numList(numList).sizeList(sizeList) .dirNumList(dirNumList) .imgNumList(imgNumList).imgSizeList(imgSizeList) .videoNumList(videoNumList).videoSizeList(videoSizeList) .audioNumList(audioNumList).audioSizeList(audioSizeList) .docNumList(docNumList).docSizeList(docSizeList) .otherNumList(otherNumList).otherSizeList(otherSizeList) .build(); } private void add(List sizeList, List numList, List subList, DataType dt) { Function > stream = dataType -> subList.stream().filter(fs -> dataType.eq(fs.getDataType())); Long size = stream.apply(dt).mapToLong(FileStatisticsDO::getSize).sum(); Integer num = stream.apply(dt).mapToInt(FileStatisticsDO::getNum).sum(); sizeList.add(size); numList.add(num); } @Getter private static class InnerQueryDate { private LocalDateTime startTime; private LocalDateTime endTime; private List dateList; private String dateType; private Long userId; public InnerQueryDate(Long userId, LocalDateTime startTime, LocalDateTime endTime) { this.userId = userId; this.startTime = startTime; this.endTime = endTime; } public InnerQueryDate invoke() { if (startTime == null) { startTime = LocalDateTime.now().plusDays(-9); } if (endTime == null) { endTime = LocalDateTime.now(); } endTime = LocalDateTime.of(endTime.toLocalDate(), LocalTime.MAX); dateList = new ArrayList<>(); dateType = DateUtils.calculationEn(startTime, endTime, dateList); return this; } } } 5.9.6 扩展FileMapper接口方法
/** * 查询下次次数前20的文件 * * @param userId * @return */ List
findDownTop20(@Param("userId") Long userId); /** * 统计时间区间内文件的下次次数和大小 * * @param userId * @param dateType 日期类型 {MONTH:按月;WEEK:按周;DAY:按日} 来统计 * @param startTime * @param endTime * @return */ List findDownSizeByDate(@Param("userId") Long userId, @Param("dateType") String dateType, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); 第2-1-2章 传统方式安装FastDFS-附FastDFS常用命令
第2-1-3章 docker-compose安装FastDFS,实现文件存储服务
第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料全套代码及资料全部完整提供,点此处下载