目录

  • 5.8 导入其他接口代码
    • 5.8.1 接口导入-分页查询附件
    • 5.8.2 接口导入-根据业务类型/业务id查询附件
  • 5.9 导入网盘服务接口
    • 5.9.1 导入FileController
    • 5.9.2 导入StatisticsController
    • 5.9.3 导入FileRestManager
    • 5.9.4 导入FileService
    • 5.9.5 导入FileServiceImpl
    • 5.9.6 扩展FileMapper接口方法

5.8 导入其他接口代码

第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<IPage> 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为空"))@GetMappingpublic R<List> 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<IPage> 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<List> 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;/** * 文件 公共代码 管理类 */@Componentpublic 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@Servicepublic 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;    }@Overridepublic 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<String, List> 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<DataType, List> 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<InnerQueryDate, List> function) {        InnerQueryDate innerQueryDate = new InnerQueryDate(userId, startTime, endTime).invoke();        List dateList = innerQueryDate.getDateList();        List list = function.apply(innerQueryDate);        //按月份分类        Map<String, List> 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<DataType, Stream> 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<DataType, Stream> 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全网最全的资料

全套代码及资料全部完整提供,点此处下载