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<Attachment>> page(FilePageReqDTO data) {
Page<Attachment> page = getPage();
attachmentService.page(page, data);
return success(page);
}

AttachmentService接口:

/**
* 查询附件分页数据
*
* @param page
* @param data
* @return
*/
IPage<Attachment> page(Page<Attachment> page, FilePageReqDTO data);

AttachmentServiceImpl类:

/**
* 查询附件分页数据
*
* @param page
* @param data
* @return
*/
public IPage<Attachment> page(Page<Attachment> page, FilePageReqDTO data) {
Attachment attachment = dozer.map(data, Attachment.class); // ${ew.customSqlSegment} 语法一定要手动eq like 等 不能用lbQ!
LbqWrapper<Attachment> wrapper = Wraps.<Attachment>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<List<AttachmentResultDTO>> 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<AttachmentResultDTO> find(String[] bizTypes, String[] bizIds);

AttachmentServiceImpl类:

/**
* 根据业务类型和业务id查询附件
*
* @param bizTypes
* @param bizIds
* @return
*/
public List<AttachmentResultDTO> 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<File> 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<File>> 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<File> 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<FolderDTO> 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<Boolean> 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<Boolean> 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<FileOverviewDTO> overview(@RequestParam(name = "userId", required = false) Long userId) {
return success(fileService.findOverview(userId, null, null));
} @ApiOperation(value = "按照类型,统计各种类型的 大小和数量", notes = "按照类型,统计当前登录人各种类型的大小和数量")
@GetMapping(value = "/type")
public R<List<FileStatisticsDO>> findAllByDataType(@RequestParam(name = "userId", required = false) Long userId) {
return success(fileService.findAllByDataType(userId));
} @ApiOperation(value = "按照时间统计各种类型的文件的数量和大小", notes = "按照时间统计各种类型的文件的数量和大小 不指定时间,默认查询一个月")
@GetMapping(value = "")
public R<FileStatisticsAllDTO> 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<File> page(IPage<File> page, FilePageReqDTO filePageReq) {
//类型和文件夹id同时为null时, 表示查询 全部文件
if (filePageReq.getFolderId() == null && filePageReq.getDataType() == null) {
filePageReq.setFolderId(DEF_PARENT_ID);
} QueryWrapper<File> query = new QueryWrapper<>();
LambdaQueryWrapper<File> 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<File> {
/**
* 保存文件夹
*
* @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<FileStatisticsDO> findAllByDataType(Long userId); /**
* 查询下载排行前20的文件
*
* @param userId
* @return
*/
List<FileStatisticsDO> 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<FileMapper, File> 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<File> lambdaUpdate =
Wraps.<File>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<File> list = super.list(Wrappers.<File>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<File> list = (List<File>) super.listByIds(Arrays.asList(ids)); if (list == null || list.size() == 0) {
return;
}
List<FileDO> 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<FileStatisticsDO> 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<String> dateList = innerQueryDate.getDateList();
String dateType = innerQueryDate.getDateType(); //不完整的数据
List<FileStatisticsDO> list = baseMapper.findNumAndSizeByUserId(userId, dateType, null, startTime, endTime); //按月份分类
Map<String, List<FileStatisticsDO>> map = list.stream().collect(groupingBy(FileStatisticsDO::getDateType)); List<Long> sizeList = new ArrayList<>();
List<Integer> numList = new ArrayList<>(); dateList.forEach((date) -> {
if (map.containsKey(date)) {
List<FileStatisticsDO> 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<FileStatisticsDO> findAllByDataType(Long userId) {
List<DataType> dataTypes = Arrays.asList(DataType.values());
List<FileStatisticsDO> list = baseMapper.findNumAndSizeByUserId(userId, null, "ALL", null, null); Map<DataType, List<FileStatisticsDO>> 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<FileStatisticsDO> 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<FileStatisticsDO>> function) {
InnerQueryDate innerQueryDate = new InnerQueryDate(userId, startTime, endTime).invoke();
List<String> dateList = innerQueryDate.getDateList(); List<FileStatisticsDO> list = function.apply(innerQueryDate); //按月份分类
Map<String, List<FileStatisticsDO>> map = list.stream().collect(groupingBy(FileStatisticsDO::getDateType)); List<Long> sizeList = new ArrayList<>(dateList.size());
List<Integer> numList = new ArrayList<>(dateList.size()); List<Integer> dirNumList = new ArrayList<>(dateList.size()); List<Long> imgSizeList = new ArrayList<>(dateList.size());
List<Integer> imgNumList = new ArrayList<>(dateList.size()); List<Long> videoSizeList = new ArrayList<>(dateList.size());
List<Integer> videoNumList = new ArrayList<>(dateList.size()); List<Long> audioSizeList = new ArrayList<>(dateList.size());
List<Integer> audioNumList = new ArrayList<>(dateList.size()); List<Long> docSizeList = new ArrayList<>(dateList.size());
List<Integer> docNumList = new ArrayList<>(dateList.size()); List<Long> otherSizeList = new ArrayList<>(dateList.size());
List<Integer> otherNumList = new ArrayList<>(dateList.size()); dateList.forEach((date) -> {
if (map.containsKey(date)) {
List<FileStatisticsDO> subList = map.get(date); Function<DataType, Stream<FileStatisticsDO>> 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<Long> sizeList, List<Integer> numList, List<FileStatisticsDO> subList, DataType dt) {
Function<DataType, Stream<FileStatisticsDO>> 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<String> 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<FileStatisticsDO> findDownTop20(@Param("userId") Long userId); /**
* 统计时间区间内文件的下次次数和大小
*
* @param userId
* @param dateType 日期类型 {MONTH:按月;WEEK:按周;DAY:按日} 来统计
* @param startTime
* @param endTime
* @return
*/
List<FileStatisticsDO> 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全网最全的资料

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

第2-3-7章 个人网盘服务接口开发-文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss的更多相关文章

  1. 第2-3-1章 文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss

    目录 文件存储服务 1. 需求背景 2. 核心功能 3. 存储策略 3.1 本地存储 3.2 FastDFS存储 3.3 云存储 3.4 minio 4. 技术设计 文件存储服务 全套代码及资料全部完 ...

  2. 使用pcs api往免费的百度网盘上传下载文件

    百度个人云盘空间大,完全免费,而且提供了pcs api供调用操作文件,在平时的项目里往里面保存一些文件是很实用的. 环境准备: 开通读写网盘的权限及获取access_token:http://blog ...

  3. C# 同步更新网盘和本地的文件夹及文件

    该程序是可以更新本地文件或更新网盘文件或者网盘和本地同步更新 下载地址:https://files.cnblogs.com/files/Wonderful-Life/UpdateFilesSync.r ...

  4. 阿里云使用js 实现OSS图片上传、获取OSS图片列表、获取图片外网访问地址(读写权限私有、读写权限公共);

    详情请参考:https://help.aliyun.com/document_detail/32069.html?spm=a2c4g.11186623.6.763.ZgC59a 或者https://h ...

  5. 第2-1-3章 docker-compose安装FastDFS,实现文件存储服务

    目录 4 docker-compose安装FastDFS 4.1 docker-compose-fastdfs.yml 4.2 nginx.conf 4.3 storage.conf 4.4 测试 4 ...

  6. 第2-1-5章 docker安装MinIO实现文件存储服务-springboot整合minio-minio全网最全的资料

    目录 1. MinIO介绍 2. MinIO应用场景 2.1 单主机单硬盘模式 2.2 单主机多硬盘模式 2.3 多主机多硬盘分布式 3. MinIO特点 4. 存储机制 5. docker安装Min ...

  7. 第1-5章 慕课网微信小程序开发学习笔记

    第1章 前言:不同的时代,不同的Web --微信小程序商城构建全栈应用 http://note.youdao.com/noteshare?id=a0e9b058853dbccf886c1a890594 ...

  8. 第2-1-4章 SpringBoot整合FastDFS文件存储服务

    目录 5 SpringBoot整合 5.1 操作步骤 5.2 项目依赖 5.3 客户端开发 5.3.1 FastDFS配置 5.3.2 FastDFS配置类 5.3.3 文件工具类 5.3.4 文件上 ...

  9. 使用百度网盘+Git,把版本控制托管到云端

    之前公司的一个项目使用SVN来做的版本控制,服务器设在我这台电脑上.然后是出于某些原因,我的电脑IP变了多次,每变一次就要重新绑定静态ip,甚是烦人.同时SVN这种集中式的版本控制服务在我关闭了我的电 ...

  10. 玩转Windows Azure存储服务——网盘

    存储服务是除了计算服务之外最重要的云服务之一.说到云存储,大家可以想到很多产品,例如:AWS S3,Google Drive,百度云盘...而在Windows Azure中,存储服务却是在默默无闻的工 ...

随机推荐

  1. KingbaseES 如何查看应用执行的SQL的执行计划

    通过explain ,我们可以获取特定SQL 的执行计划.但对于同一条SQL,不同的变量.不同的系统负荷,其执行计划可能不同.我们要如何取得SQL执行时间点的执行计划?KingbaseES 提供了 a ...

  2. DFS算法-求集合的所有子集

    目录 1. 题目来源 2. 普通方法 1. 思路 2. 代码 3. 运行结果 3. DFS算法 1. 概念 2. 解题思路 3. 代码 4. 运行结果 4. 对比 1. 题目来源 牛客网,集合的所有子 ...

  3. win10设置vmware 虚拟机开机自启

    Windows10设置VMware虚拟机开机自启的具体步骤如下: 一.配置vmrun环境变量 1)找到VMware的安装目录,并将目录路径拷贝进入环境变量进行添加,如下图 2)检查添加的环境变量是否生 ...

  4. 在Windows Server 2019上安装edge浏览器

    在Windows 2016和2019的正式版本中是不带Edge浏览器的.有些工具.网站也不支持IE浏览器了.对于偶尔需要在服务器上访问这些站点的管理员来说有些不方便.不过可以通过安装三方浏览器或者Ed ...

  5. 从EDR的火热看安全产品的发展

    从EDR的火热看安全产品的发展 2021年4月8日23:13 当开始写这篇博客时,外面正是护网进行得如火如荼的时候.作为一个产品经理,在吃瓜的同时,也在思考着安全产品的发展.这几年一些看得到的变化在深 ...

  6. 【一月一本技术书】-【MySQL是怎样运行的】- 8月

    mysql 基础 mysql分为 客戶端/服务端 客户端向服务端发送一段文本(mysql语句),服务器处理后向客户端进程返回一段文本. 查询请求执行过程 客户端->处理连接->查询缓存-& ...

  7. Django manage.py 命令详解

    manage.py 查看命令的作用的语句 C:\Users\Administrator> python manage.py help Type 'manage.py help <subco ...

  8. MasaFramework的MinimalAPI设计

    在以前的MVC引用程序中,控制器负责接收输入信息.执行.编排操作并返回响应,它是一个功能齐全的框架,它提供了过滤器.内置了模型绑定与验证,并提供了很多可扩展的管道,但它偏重,不像其它语言是通过更加简洁 ...

  9. MySQL主从同步报错故障处理记录

    从库上记录删除失败,Error_code: 1032 问题描述:在master上删除一条记录,而slave上找不到,导致报错 Last_SQL_Error: Could not execute Del ...

  10. 第三章:模版层 - 2:Django内置模板标签

    Django内置标签总览 可以查询下表来总览Django的内置标签: 标签 说明 autoescape 自动转义开关 block 块引用 comment 注释 csrf_token CSRF令牌 cy ...