feat:增加登录和文件模块
This commit is contained in:
65
src/main/java/com/cxx/food/controller/FileController.java
Normal file
65
src/main/java/com/cxx/food/controller/FileController.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package com.cxx.food.controller;
|
||||||
|
|
||||||
|
import com.cxx.food.dto.file.ChunkInfoDto;
|
||||||
|
import com.cxx.food.dto.file.ChunkResultDto;
|
||||||
|
import com.cxx.food.dto.file.FileInfoDto;
|
||||||
|
import com.cxx.food.dto.file.FileRecordDto;
|
||||||
|
import com.cxx.food.service.FileService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/file")
|
||||||
|
@Tag(name = "文件管理")
|
||||||
|
public class FileController {
|
||||||
|
@Resource
|
||||||
|
private FileService fileService;
|
||||||
|
|
||||||
|
@Operation(summary = "上传文件")
|
||||||
|
@PostMapping(value = "", headers = "content-type=multipart/form-data")
|
||||||
|
public FileRecordDto uploadFile(@RequestPart("file") MultipartFile file,
|
||||||
|
@RequestParam("path") String path,
|
||||||
|
@RequestParam("md5") String md5) {
|
||||||
|
return fileService.uploadFile(file, path, md5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "上传文件块")
|
||||||
|
@PostMapping("/chunk")
|
||||||
|
public Boolean uploadChunk(ChunkInfoDto chunkInfo,
|
||||||
|
String path) {
|
||||||
|
return fileService.uploadChunk(chunkInfo, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "验证当前文件块是否上传")
|
||||||
|
@GetMapping("/chunk")
|
||||||
|
public ChunkResultDto checkChunk(@RequestParam String identifier,
|
||||||
|
@RequestParam String filename,
|
||||||
|
@RequestParam String path) {
|
||||||
|
return fileService.checkChunk(identifier, filename, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除当前已上传的文件块")
|
||||||
|
@DeleteMapping("/chunk")
|
||||||
|
public Boolean deleteChunk(@RequestParam String identifier,
|
||||||
|
@RequestParam String path) {
|
||||||
|
return fileService.deleteChunk(identifier, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "合并文件")
|
||||||
|
@PostMapping("/chunk/merge")
|
||||||
|
public FileRecordDto mergeFile(@RequestParam String filename,
|
||||||
|
@RequestParam String path) {
|
||||||
|
return fileService.mergeFile(filename, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "获取文件夹目录")
|
||||||
|
@GetMapping("/catalog")
|
||||||
|
public List<FileInfoDto> getFolderInfo(@RequestParam String folderName) {
|
||||||
|
return fileService.getFolderInfo(folderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,10 +6,7 @@ import com.cxx.food.service.SessionService;
|
|||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/session")
|
@RequestMapping("/session")
|
||||||
@@ -21,8 +18,14 @@ public class SessionController {
|
|||||||
@Operation(summary = "创建会话")
|
@Operation(summary = "创建会话")
|
||||||
@PostMapping("")
|
@PostMapping("")
|
||||||
@SaIgnore
|
@SaIgnore
|
||||||
public SessionDto createSession(@RequestParam("name") String name,
|
public SessionDto create(@RequestParam("username") String username,
|
||||||
@RequestParam("password") String password) {
|
@RequestParam("password") String password) {
|
||||||
return sessionService.create(name, password);
|
return sessionService.create(username, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "退出会话")
|
||||||
|
@DeleteMapping("")
|
||||||
|
public Boolean abort(@RequestParam("username") String username) {
|
||||||
|
return sessionService.abort(username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
27
src/main/java/com/cxx/food/controller/UserController.java
Normal file
27
src/main/java/com/cxx/food/controller/UserController.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package com.cxx.food.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaIgnore;
|
||||||
|
import com.cxx.food.dto.ReadView;
|
||||||
|
import com.cxx.food.dto.UserDto;
|
||||||
|
import com.cxx.food.dto.WriteView;
|
||||||
|
import com.cxx.food.service.UserService;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
|
@Tag(name = "用户管理")
|
||||||
|
public class UserController {
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@Operation(summary = "注册用户")
|
||||||
|
@PostMapping("")
|
||||||
|
@SaIgnore
|
||||||
|
public Boolean createSession(@JsonView(WriteView.class) @RequestBody UserDto userDto) {
|
||||||
|
return userService.register(userDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,22 +15,24 @@ public interface FoodDao {
|
|||||||
IPage<SummaryDto> querySummaryByPage(IPage<SummaryDto> page,
|
IPage<SummaryDto> querySummaryByPage(IPage<SummaryDto> page,
|
||||||
@Param("query") FoodQueryVo foodQueryVo);
|
@Param("query") FoodQueryVo foodQueryVo);
|
||||||
|
|
||||||
List<SummaryDto> querySummary(@Param("query") FoodQueryVo foodQueryVo);
|
List<SummaryDto> querySummary(@Param("query") FoodQueryVo foodQueryVo,
|
||||||
|
@Param("user") String user);
|
||||||
|
|
||||||
List<RecordDto> queryRecordById(@Param("id") Long id);
|
List<RecordDto> queryRecordById(@Param("id") Long id);
|
||||||
|
|
||||||
List<RecordDto> queryRecord(@Param("startDate") String startDate,
|
List<RecordDto> queryRecord(@Param("startDate") String startDate,
|
||||||
@Param("endDate") String endDate);
|
@Param("endDate") String endDate,
|
||||||
|
@Param("user") String user);
|
||||||
|
|
||||||
StatsDto queryStats();
|
StatsDto queryStats(@Param("user") String user);
|
||||||
|
|
||||||
List<StatsChartDto> queryRecordStats();
|
List<StatsChartDto> queryRecordStats(@Param("user") String user);
|
||||||
|
|
||||||
List<StatsChartDto> queryCategoryStats();
|
List<StatsChartDto> queryCategoryStats(@Param("user") String user);
|
||||||
|
|
||||||
List<StatsChartDto> queryRankStats();
|
List<StatsChartDto> queryRankStats(@Param("user") String user);
|
||||||
|
|
||||||
List<String> queryCategory();
|
List<String> queryCategory(@Param("user") String user);
|
||||||
|
|
||||||
void insertMaterial(@Param("foodId") Long foodId,
|
void insertMaterial(@Param("foodId") Long foodId,
|
||||||
@Param("list") List<MaterialDto> list);
|
@Param("list") List<MaterialDto> list);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.cxx.food.dto;
|
package com.cxx.food.dto;
|
||||||
|
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -10,5 +11,8 @@ import lombok.Setter;
|
|||||||
public class SessionDto {
|
public class SessionDto {
|
||||||
@Schema(description = "令牌")
|
@Schema(description = "令牌")
|
||||||
private SaTokenInfo saToken;
|
private SaTokenInfo saToken;
|
||||||
|
|
||||||
|
@Schema(description = "用户信息")
|
||||||
|
private UserDto userInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
src/main/java/com/cxx/food/dto/UserDto.java
Normal file
73
src/main/java/com/cxx/food/dto/UserDto.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package com.cxx.food.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@JsonView(PlainView.class)
|
||||||
|
public class UserDto {
|
||||||
|
@Schema(description = "id")
|
||||||
|
@JsonView(ReadView.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "用户名称")
|
||||||
|
@NotBlank(message = "用户名称不能为空")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Schema(description = "密码")
|
||||||
|
@NotBlank(message = "密码不能为空")
|
||||||
|
@JsonView(WriteView.class)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
// @Schema(description = "性别")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private Integer gender;
|
||||||
|
//
|
||||||
|
// @Schema(description = "身份证号")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private String idNumber;
|
||||||
|
//
|
||||||
|
// @Schema(description = "手机号码")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private String phoneNumber;
|
||||||
|
//
|
||||||
|
// @Schema(description = "电子邮件")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private String email;
|
||||||
|
//
|
||||||
|
// @Schema(description = "生日")
|
||||||
|
// @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||||
|
// private Date birthDate;
|
||||||
|
|
||||||
|
@Schema(description = "头像")
|
||||||
|
@JsonView(ReadView.class)
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
// @Schema(description = "地区")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private List<String> area;
|
||||||
|
//
|
||||||
|
// @Schema(description = "地址")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private String address;
|
||||||
|
//
|
||||||
|
// @Schema(description = "职业")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private String job;
|
||||||
|
//
|
||||||
|
// @Schema(description = "标签")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private List<String> tags;
|
||||||
|
//
|
||||||
|
// @Schema(description = "描述")
|
||||||
|
// @JsonView(ReadView.class)
|
||||||
|
// private String description;
|
||||||
|
}
|
||||||
22
src/main/java/com/cxx/food/dto/file/ChunkInfoDto.java
Normal file
22
src/main/java/com/cxx/food/dto/file/ChunkInfoDto.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package com.cxx.food.dto.file;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ChunkInfoDto {
|
||||||
|
/**
|
||||||
|
* 当前文件块,从1开始
|
||||||
|
*/
|
||||||
|
private Integer chunkNumber;
|
||||||
|
/**
|
||||||
|
* 文件名
|
||||||
|
*/
|
||||||
|
private String filename;
|
||||||
|
/**
|
||||||
|
* 块内容
|
||||||
|
*/
|
||||||
|
private transient MultipartFile multipartFile;
|
||||||
|
}
|
||||||
20
src/main/java/com/cxx/food/dto/file/ChunkResultDto.java
Normal file
20
src/main/java/com/cxx/food/dto/file/ChunkResultDto.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package com.cxx.food.dto.file;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ChunkResultDto {
|
||||||
|
/**
|
||||||
|
* 是否跳过上传(已上传的可以直接跳过,达到秒传的效果)
|
||||||
|
*/
|
||||||
|
private boolean isSkipUpload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已经上传的文件块编号,可以跳过,断点续传
|
||||||
|
*/
|
||||||
|
private List<Integer> uploadedChunkList;
|
||||||
|
}
|
||||||
17
src/main/java/com/cxx/food/dto/file/FileInfoDto.java
Normal file
17
src/main/java/com/cxx/food/dto/file/FileInfoDto.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package com.cxx.food.dto.file;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class FileInfoDto {
|
||||||
|
private String name;
|
||||||
|
private String type;
|
||||||
|
private String size;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date createDate;
|
||||||
|
}
|
||||||
14
src/main/java/com/cxx/food/dto/file/FileRecordDto.java
Normal file
14
src/main/java/com/cxx/food/dto/file/FileRecordDto.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package com.cxx.food.dto.file;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class FileRecordDto {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private String md5;
|
||||||
|
private String path;
|
||||||
|
private String url;
|
||||||
|
}
|
||||||
24
src/main/java/com/cxx/food/entity/FileRecord.java
Normal file
24
src/main/java/com/cxx/food/entity/FileRecord.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package com.cxx.food.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.cxx.framework.data.AbstractEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("file_record")
|
||||||
|
public class FileRecord extends AbstractEntity {
|
||||||
|
@TableField("name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@TableField("md5")
|
||||||
|
private String md5;
|
||||||
|
|
||||||
|
@TableField("path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@TableField("url")
|
||||||
|
private String url;
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ public class Record extends AbstractIdEntity {
|
|||||||
private Long foodId;
|
private Long foodId;
|
||||||
|
|
||||||
@TableField("person")
|
@TableField("person")
|
||||||
private Long person;
|
private String person;
|
||||||
|
|
||||||
@TableField("date")
|
@TableField("date")
|
||||||
private Date date;
|
private Date date;
|
||||||
|
|||||||
9
src/main/java/com/cxx/food/mapper/FileRecordMapper.java
Normal file
9
src/main/java/com/cxx/food/mapper/FileRecordMapper.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package com.cxx.food.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.cxx.food.entity.FileRecord;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface FileRecordMapper extends BaseMapper<FileRecord> {
|
||||||
|
}
|
||||||
48
src/main/java/com/cxx/food/service/FileService.java
Normal file
48
src/main/java/com/cxx/food/service/FileService.java
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package com.cxx.food.service;
|
||||||
|
|
||||||
|
import com.cxx.food.dto.file.ChunkInfoDto;
|
||||||
|
import com.cxx.food.dto.file.ChunkResultDto;
|
||||||
|
import com.cxx.food.dto.file.FileInfoDto;
|
||||||
|
import com.cxx.food.dto.file.FileRecordDto;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface FileService {
|
||||||
|
FileRecordDto uploadFile(MultipartFile file, String path, String md5);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件块
|
||||||
|
* @param chunkInfo 文件块信息
|
||||||
|
* @param path 上传路径
|
||||||
|
* @return 是否上传成功
|
||||||
|
*/
|
||||||
|
Boolean uploadChunk(ChunkInfoDto chunkInfo, String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查文件块信息
|
||||||
|
* @param identifier 唯一标识
|
||||||
|
* @param filename 文件名
|
||||||
|
* @param path 上传文件夹路径
|
||||||
|
* @return 检查结果
|
||||||
|
*/
|
||||||
|
ChunkResultDto checkChunk(String identifier, String filename, String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件块
|
||||||
|
* @param identifier 唯一标识
|
||||||
|
* @param path 上传文件夹路径
|
||||||
|
* @return 是否删除成功
|
||||||
|
*/
|
||||||
|
Boolean deleteChunk(String identifier, String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并文件
|
||||||
|
* @param filename 文件名
|
||||||
|
* @param path 上传文件夹路径
|
||||||
|
* @return 是否合并成功
|
||||||
|
*/
|
||||||
|
FileRecordDto mergeFile(String filename, String path);
|
||||||
|
|
||||||
|
List<FileInfoDto> getFolderInfo(String folderName);
|
||||||
|
}
|
||||||
@@ -4,5 +4,7 @@ package com.cxx.food.service;
|
|||||||
import com.cxx.food.dto.SessionDto;
|
import com.cxx.food.dto.SessionDto;
|
||||||
|
|
||||||
public interface SessionService {
|
public interface SessionService {
|
||||||
SessionDto create(String name, String password);
|
SessionDto create(String username, String password);
|
||||||
|
|
||||||
|
Boolean abort(String username);
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/main/java/com/cxx/food/service/UserService.java
Normal file
9
src/main/java/com/cxx/food/service/UserService.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package com.cxx.food.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.cxx.food.dto.SessionDto;
|
||||||
|
import com.cxx.food.dto.UserDto;
|
||||||
|
|
||||||
|
public interface UserService {
|
||||||
|
Boolean register(UserDto userDto);
|
||||||
|
}
|
||||||
204
src/main/java/com/cxx/food/service/impl/FileServiceImpl.java
Normal file
204
src/main/java/com/cxx/food/service/impl/FileServiceImpl.java
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
package com.cxx.food.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.cxx.food.constant.FileConstant;
|
||||||
|
import com.cxx.food.dto.file.ChunkInfoDto;
|
||||||
|
import com.cxx.food.dto.file.ChunkResultDto;
|
||||||
|
import com.cxx.food.dto.file.FileInfoDto;
|
||||||
|
import com.cxx.food.dto.file.FileRecordDto;
|
||||||
|
import com.cxx.food.entity.FileRecord;
|
||||||
|
import com.cxx.food.mapper.FileRecordMapper;
|
||||||
|
import com.cxx.food.service.FileService;
|
||||||
|
import com.cxx.food.util.FileUtils;
|
||||||
|
import com.cxx.food.util.UploadFileUtil;
|
||||||
|
import com.cxx.framework.web.CustomException;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class FileServiceImpl implements FileService {
|
||||||
|
@Value("${file.path}")
|
||||||
|
private String fileRootPath;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FileRecordMapper fileRecordMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileRecordDto uploadFile(MultipartFile multipartFile, String path, String md5) {
|
||||||
|
UploadFileUtil.checkDirIsExist(getFilePath(path));
|
||||||
|
|
||||||
|
String filename = multipartFile.getOriginalFilename();
|
||||||
|
String newPath = path + File.separator + md5 + "." + FilenameUtils.getExtension(filename);
|
||||||
|
File newFile = new File(getFilePath(newPath));
|
||||||
|
|
||||||
|
saveFile(multipartFile, newFile);
|
||||||
|
|
||||||
|
// 这里的url需要加上 WebMvcConfig 中设置的前缀
|
||||||
|
String url = FileConstant.FILE_URL_PREFIX + File.separator + newPath;
|
||||||
|
return getFileRecord(filename, md5, path, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean uploadChunk(ChunkInfoDto chunkInfo, String path) {
|
||||||
|
MultipartFile file = chunkInfo.getMultipartFile();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 校验路径是否存在
|
||||||
|
UploadFileUtil.checkDirIsExist(getFilePath(path));
|
||||||
|
// 2. 获取文件块路径
|
||||||
|
Path chunkPath = Paths.get(UploadFileUtil.generateChunkPath(getFilePath(path), chunkInfo));
|
||||||
|
// 3. 将文件块写入指定路径
|
||||||
|
Files.write(chunkPath, file.getBytes());
|
||||||
|
} catch (IOException exception) {
|
||||||
|
log.error("文件上传块失败: {}", exception.getMessage());
|
||||||
|
throw new CustomException("文件上传块失败: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkResultDto checkChunk(String identifier, String filename, String path) {
|
||||||
|
ChunkResultDto chunkResult = new ChunkResultDto();
|
||||||
|
List<Integer> uploadedChunkList = new ArrayList<>();
|
||||||
|
|
||||||
|
String folder = getFilePath(path) + File.separator + identifier;
|
||||||
|
String file = folder + File.separator + filename;
|
||||||
|
|
||||||
|
// 判断文件夹是否存在
|
||||||
|
if (UploadFileUtil.fileExists(folder)) {
|
||||||
|
// 先判断整个文件是否已经上传过了,如果是,则告诉前端跳过上传,实现秒传
|
||||||
|
if (UploadFileUtil.fileExists(file)) {
|
||||||
|
chunkResult.setSkipUpload(true);
|
||||||
|
chunkResult.setUploadedChunkList(uploadedChunkList);
|
||||||
|
log.info("完整文件已存在,直接跳过上传,实现秒传");
|
||||||
|
} else {
|
||||||
|
chunkResult.setSkipUpload(false);
|
||||||
|
// 获取已经上传的文件块
|
||||||
|
chunkResult.setUploadedChunkList(UploadFileUtil.getUploadedChunkList(folder, filename));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chunkResult.setSkipUpload(false);
|
||||||
|
chunkResult.setUploadedChunkList(uploadedChunkList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunkResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteChunk(String identifier, String path) {
|
||||||
|
String folder = getFilePath(path) + File.separator + identifier;
|
||||||
|
log.info("开始删除文件: " + folder);
|
||||||
|
|
||||||
|
// 判断文件夹是否存在
|
||||||
|
if (UploadFileUtil.fileExists(folder)) {
|
||||||
|
UploadFileUtil.deleteDirectory(folder);
|
||||||
|
} else {
|
||||||
|
throw new CustomException("文件: " + folder + "不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileRecordDto mergeFile(String filename, String path) {
|
||||||
|
String uuid = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
String newFilename = uuid + "." + FilenameUtils.getExtension(filename);
|
||||||
|
try {
|
||||||
|
UploadFileUtil.mergeFile(newFilename, getFilePath(path));
|
||||||
|
} catch (IOException exception) {
|
||||||
|
throw new CustomException("合并文件: " + filename + " 失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
String newPath = path + File.separator + newFilename;
|
||||||
|
String url = FileConstant.FILE_URL_PREFIX + File.separator + newPath;
|
||||||
|
return getFileRecord(filename, uuid, path, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileInfoDto> getFolderInfo(String folderName) {
|
||||||
|
File folder = new File(folderName);
|
||||||
|
List<FileInfoDto> fileInfoList = new ArrayList<>();
|
||||||
|
if (folder.exists() && folder.isDirectory()) {
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
List<FileInfoDto> folderInfoList = new ArrayList<>();
|
||||||
|
List<FileInfoDto> fileInfoSubList = new ArrayList<>();
|
||||||
|
for (File file : files) {
|
||||||
|
FileInfoDto fileInfo = new FileInfoDto();
|
||||||
|
fileInfo.setName(file.getName());
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
fileInfo.setType("文件夹");
|
||||||
|
fileInfo.setSize("-");
|
||||||
|
folderInfoList.add(fileInfo);
|
||||||
|
} else {
|
||||||
|
fileInfo.setType(FileUtils.getFileType(file.getName()));
|
||||||
|
fileInfo.setSize(FileUtils.formatSize(file.length()));
|
||||||
|
fileInfoSubList.add(fileInfo);
|
||||||
|
}
|
||||||
|
fileInfo.setCreateDate(new Date(file.lastModified()));
|
||||||
|
}
|
||||||
|
fileInfoList.addAll(folderInfoList);
|
||||||
|
fileInfoList.addAll(fileInfoSubList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveFile(MultipartFile multipartFile, File file) {
|
||||||
|
// 如果文件不存在
|
||||||
|
if (!file.exists()) {
|
||||||
|
try {
|
||||||
|
// 3. 如果不存在则创建文件
|
||||||
|
multipartFile.transferTo(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new CustomException("文件上传失败:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileRecordDto getFileRecord(String filename, String md5, String path, String url) {
|
||||||
|
FileRecord fileRecord = new FileRecord();
|
||||||
|
fileRecord.setName(filename);
|
||||||
|
fileRecord.setMd5(md5);
|
||||||
|
fileRecord.setPath(path);
|
||||||
|
fileRecord.setUrl(url);
|
||||||
|
fileRecord.setId(saveDatabase(fileRecord, md5));
|
||||||
|
|
||||||
|
// 4. 返回文件信息
|
||||||
|
FileRecordDto fileRecordDto = new FileRecordDto();
|
||||||
|
BeanUtils.copyProperties(fileRecord, fileRecordDto);
|
||||||
|
|
||||||
|
return fileRecordDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long saveDatabase(FileRecord fileRecord, String md5) {
|
||||||
|
LambdaQueryWrapper<FileRecord> queryWrapper = Wrappers.lambdaQuery(FileRecord.class);
|
||||||
|
FileRecord dbFileRecord = fileRecordMapper.selectOne(queryWrapper.eq(FileRecord::getMd5, md5));
|
||||||
|
if (Objects.isNull(dbFileRecord)) {
|
||||||
|
fileRecordMapper.insert(fileRecord);
|
||||||
|
return fileRecord.getId();
|
||||||
|
} else {
|
||||||
|
return dbFileRecord.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFilePath(String path) {
|
||||||
|
return fileRootPath + path;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.cxx.food.service.impl;
|
package com.cxx.food.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
@@ -90,12 +91,22 @@ public class FoodServiceImpl implements FoodService {
|
|||||||
public Boolean addRecord(RecordDto recordDto) {
|
public Boolean addRecord(RecordDto recordDto) {
|
||||||
LambdaQueryWrapper<Recipe> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<Recipe> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
Recipe recipe = recipeMapper.selectOne(queryWrapper.eq(Recipe::getName, recordDto.getName()));
|
Recipe recipe = recipeMapper.selectOne(queryWrapper.eq(Recipe::getName, recordDto.getName()));
|
||||||
|
long recipeId;
|
||||||
if (recipe == null) {
|
if (recipe == null) {
|
||||||
throw new CustomException("该菜谱不存在");
|
Recipe newRecipe = new Recipe();
|
||||||
|
newRecipe.setName(recordDto.getName());
|
||||||
|
newRecipe.setCategory("其他");
|
||||||
|
newRecipe.setRecommendRate(0);
|
||||||
|
newRecipe.setRemark("");
|
||||||
|
recipeMapper.insert(newRecipe);
|
||||||
|
recipeId = newRecipe.getId();
|
||||||
|
} else {
|
||||||
|
recipeId = recipe.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
Record record = new Record();
|
Record record = new Record();
|
||||||
record.setFoodId(recipe.getId());
|
record.setFoodId(recipeId);
|
||||||
|
record.setPerson((String) StpUtil.getLoginId());
|
||||||
BeanUtils.copyProperties(recordDto, record);
|
BeanUtils.copyProperties(recordDto, record);
|
||||||
recordMapper.insert(record);
|
recordMapper.insert(record);
|
||||||
|
|
||||||
@@ -164,7 +175,7 @@ public class FoodServiceImpl implements FoodService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SummaryDto> querySummary(FoodQueryVo foodQueryVo) {
|
public List<SummaryDto> querySummary(FoodQueryVo foodQueryVo) {
|
||||||
return foodDao.querySummary(foodQueryVo);
|
return foodDao.querySummary(foodQueryVo, StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -184,7 +195,7 @@ public class FoodServiceImpl implements FoodService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<RecordDto> queryRecord(String startDate, String endDate) {
|
public List<RecordDto> queryRecord(String startDate, String endDate) {
|
||||||
return foodDao.queryRecord(startDate, endDate);
|
return foodDao.queryRecord(startDate, endDate, StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -195,26 +206,26 @@ public class FoodServiceImpl implements FoodService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> queryCategory() {
|
public List<String> queryCategory() {
|
||||||
return foodDao.queryCategory();
|
return foodDao.queryCategory(StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatsDto queryStats() {
|
public StatsDto queryStats() {
|
||||||
return foodDao.queryStats();
|
return foodDao.queryStats(StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<StatsChartDto> queryRecordStats() {
|
public List<StatsChartDto> queryRecordStats() {
|
||||||
return foodDao.queryRecordStats();
|
return foodDao.queryRecordStats(StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<StatsChartDto> queryCategoryStats() {
|
public List<StatsChartDto> queryCategoryStats() {
|
||||||
return foodDao.queryCategoryStats();
|
return foodDao.queryCategoryStats(StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<StatsChartDto> queryRankStats() {
|
public List<StatsChartDto> queryRankStats() {
|
||||||
return foodDao.queryRankStats();
|
return foodDao.queryRankStats(StpUtil.getLoginIdAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import cn.dev33.satoken.stp.StpUtil;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.cxx.food.dto.SessionDto;
|
import com.cxx.food.dto.SessionDto;
|
||||||
|
import com.cxx.food.dto.UserDto;
|
||||||
|
import com.cxx.food.entity.User;
|
||||||
|
import com.cxx.food.mapper.UserMapper;
|
||||||
import com.cxx.food.service.SessionService;
|
import com.cxx.food.service.SessionService;
|
||||||
import com.cxx.framework.web.CustomException;
|
import com.cxx.framework.web.CustomException;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -15,13 +18,42 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class SessionServiceImpl implements SessionService {
|
public class SessionServiceImpl implements SessionService {
|
||||||
|
@Resource
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionDto create(String name, String password) {
|
public SessionDto create(String username, String password) {
|
||||||
|
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery(User.class).eq(User::getUsername, username);
|
||||||
|
User user = userMapper.selectOne(queryWrapper);
|
||||||
|
if (user == null) {
|
||||||
|
throw new CustomException("该用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BCrypt.checkpw(password, user.getPassword())) {
|
||||||
|
throw new CustomException("密码不正确");
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDto userDto = new UserDto();
|
||||||
|
BeanUtils.copyProperties(user, userDto);
|
||||||
|
|
||||||
SessionDto sessionDto = new SessionDto();
|
SessionDto sessionDto = new SessionDto();
|
||||||
StpUtil.login(645808454946885L);
|
StpUtil.login(user.getId());
|
||||||
sessionDto.setSaToken(StpUtil.getTokenInfo());
|
sessionDto.setSaToken(StpUtil.getTokenInfo());
|
||||||
|
sessionDto.setUserInfo(userDto);
|
||||||
|
|
||||||
return sessionDto;
|
return sessionDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean abort(String username) {
|
||||||
|
LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery(User.class).eq(User::getUsername, username);
|
||||||
|
User user = userMapper.selectOne(queryWrapper);
|
||||||
|
if (user == null) {
|
||||||
|
throw new CustomException("该用户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
StpUtil.logout(user.getId());
|
||||||
|
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/main/java/com/cxx/food/service/impl/UserServiceImpl.java
Normal file
34
src/main/java/com/cxx/food/service/impl/UserServiceImpl.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.cxx.food.service.impl;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.dev33.satoken.secure.BCrypt;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.cxx.food.dto.UserDto;
|
||||||
|
import com.cxx.food.entity.User;
|
||||||
|
import com.cxx.food.mapper.UserMapper;
|
||||||
|
import com.cxx.food.service.UserService;
|
||||||
|
import com.cxx.framework.web.CustomException;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserServiceImpl implements UserService {
|
||||||
|
@Resource
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean register(UserDto userDto) {
|
||||||
|
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (userMapper.exists(queryWrapper.eq(User::getUsername, userDto.getUsername()))) {
|
||||||
|
throw new CustomException("该用户已注册");
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
BeanUtils.copyProperties(userDto, user);
|
||||||
|
user.setPassword(BCrypt.hashpw(userDto.getPassword(), BCrypt.gensalt()));
|
||||||
|
|
||||||
|
return userMapper.insert(user) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/main/java/com/cxx/food/util/FileUtils.java
Normal file
28
src/main/java/com/cxx/food/util/FileUtils.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package com.cxx.food.util;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FileUtils {
|
||||||
|
public static String getFileType(String fileName) {
|
||||||
|
int lastIndex = fileName.lastIndexOf('.');
|
||||||
|
if (lastIndex != -1) {
|
||||||
|
return fileName.substring(lastIndex + 1);
|
||||||
|
}
|
||||||
|
return "未知类型";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatSize(long size) {
|
||||||
|
if (size < 1024) {
|
||||||
|
return size + " B";
|
||||||
|
} else if (size < 1024 * 1024) {
|
||||||
|
return String.format("%.2f KB", (double) size / 1024);
|
||||||
|
} else if (size < 1024 * 1024 * 1024) {
|
||||||
|
return String.format("%.2f MB", (double) size / (1024 * 1024));
|
||||||
|
} else {
|
||||||
|
return String.format("%.2f GB", (double) size / (1024 * 1024 * 1024));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
173
src/main/java/com/cxx/food/util/UploadFileUtil.java
Normal file
173
src/main/java/com/cxx/food/util/UploadFileUtil.java
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package com.cxx.food.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.file.FileNameUtil;
|
||||||
|
import com.cxx.food.dto.file.ChunkInfoDto;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: chenxiuxiang
|
||||||
|
* @Date: 2023/7/24 14:49
|
||||||
|
* @Description: 上传文件工具类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class UploadFileUtil {
|
||||||
|
private static final String FILE_SEPARATOR = "_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验文件夹是否存在
|
||||||
|
*
|
||||||
|
* @param path 路径
|
||||||
|
*/
|
||||||
|
public static void checkDirIsExist(String path) {
|
||||||
|
File dir = new File(path);
|
||||||
|
if (!dir.exists() && !dir.isDirectory()) {
|
||||||
|
boolean mkdir = dir.mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件路径
|
||||||
|
*
|
||||||
|
* @param path 上传文件夹路径
|
||||||
|
* @param chunkInfo 分片文件信息
|
||||||
|
* @return 文件路径
|
||||||
|
*/
|
||||||
|
public static String generateChunkPath(String path, ChunkInfoDto chunkInfo) {
|
||||||
|
return path + File.separator + chunkInfo.getFilename() + FILE_SEPARATOR + chunkInfo.getChunkNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> getUploadedChunkList(String folder, String filename) {
|
||||||
|
List<Integer> uploadedChunkList = new ArrayList<>();
|
||||||
|
|
||||||
|
// 获取文件夹下所有的文件
|
||||||
|
try (Stream<Path> list = Files.list(Paths.get(folder))) {
|
||||||
|
// 去除需要合并的文件
|
||||||
|
list.filter(path -> !path.getFileName().toString().equals(filename))
|
||||||
|
// 循环遍历文件 将已经上传的文件序号添加至列表中
|
||||||
|
.forEach(path -> {
|
||||||
|
String chunkPath = path.getFileName().toString();
|
||||||
|
int index = chunkPath.lastIndexOf(FILE_SEPARATOR);
|
||||||
|
uploadedChunkList.add(Integer.valueOf(chunkPath.substring(index + 1)));
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uploadedChunkList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件合并
|
||||||
|
*/
|
||||||
|
public static void mergeFile(String filename, String path) throws IOException {
|
||||||
|
// 判断文件是否存在
|
||||||
|
String file = path + File.separator + filename;
|
||||||
|
if (fileExists(file)) {
|
||||||
|
deleteFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不存在的话,进行合并
|
||||||
|
Files.createFile(Paths.get(file));
|
||||||
|
|
||||||
|
// 获取文件夹下所有的文件
|
||||||
|
try (Stream<Path> list = Files.list(Paths.get(path))) {
|
||||||
|
// 保留后缀包含分隔符的
|
||||||
|
list.filter(chunkPath -> FileNameUtil.getSuffix(chunkPath.getFileName().toString()).contains(FILE_SEPARATOR))
|
||||||
|
// 按照文件名排序
|
||||||
|
.sorted((o1, o2) -> {
|
||||||
|
String p1 = o1.getFileName().toString();
|
||||||
|
String p2 = o2.getFileName().toString();
|
||||||
|
int i1 = p1.lastIndexOf(FILE_SEPARATOR);
|
||||||
|
int i2 = p2.lastIndexOf(FILE_SEPARATOR);
|
||||||
|
return Integer.valueOf(p1.substring(i1 + 1))
|
||||||
|
.compareTo(Integer.valueOf(p2.substring(i2 + 1)));
|
||||||
|
})
|
||||||
|
// 循环写入到文件中
|
||||||
|
.forEach(chunkPath -> {
|
||||||
|
try {
|
||||||
|
// 以追加的形式写入文件
|
||||||
|
Files.write(Paths.get(file), Files.readAllBytes(chunkPath), StandardOpenOption.APPEND);
|
||||||
|
// 合并后删除该块
|
||||||
|
Files.delete(chunkPath);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
log.error("写入文件失败: " + exception.getMessage());
|
||||||
|
throw new RuntimeException(exception);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件的全路径名判断文件是否存在
|
||||||
|
*/
|
||||||
|
public static boolean fileExists(String file) {
|
||||||
|
Path path = Paths.get(file);
|
||||||
|
return Files.exists(path, LinkOption.NOFOLLOW_LINKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除目录(文件夹)以及目录下的文件
|
||||||
|
*
|
||||||
|
* @param sPath 被删除目录的文件路径
|
||||||
|
* @return 目录删除成功返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public static boolean deleteDirectory(String sPath) {
|
||||||
|
// 如果sPath不以文件分隔符结尾,自动添加文件分隔符
|
||||||
|
if (!sPath.endsWith(File.separator)) {
|
||||||
|
sPath = sPath + File.separator;
|
||||||
|
}
|
||||||
|
File dirFile = new File(sPath);
|
||||||
|
// 如果dir对应的文件不存在,或者不是一个目录,则退出
|
||||||
|
if (!dirFile.exists() || !dirFile.isDirectory()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flag = true;
|
||||||
|
// 删除文件夹下的所有文件(包括子目录)
|
||||||
|
File[] files = dirFile.listFiles();
|
||||||
|
for (File file : Objects.requireNonNull(files)) {
|
||||||
|
// 删除子文件
|
||||||
|
if (file.isFile()) {
|
||||||
|
flag = deleteFile(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
// 删除子目录
|
||||||
|
else {
|
||||||
|
flag = deleteDirectory(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
if (!flag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("文件删除成功");
|
||||||
|
// 删除当前目录
|
||||||
|
return dirFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除单个文件
|
||||||
|
*
|
||||||
|
* @param sPath 被删除文件的文件名
|
||||||
|
* @return 单个文件删除成功返回true,否则返回false
|
||||||
|
*/
|
||||||
|
public static boolean deleteFile(String sPath) {
|
||||||
|
boolean flag = false;
|
||||||
|
File file = new File(sPath);
|
||||||
|
// 路径为文件且不为空则进行删除
|
||||||
|
if (file.isFile() && file.exists()) {
|
||||||
|
flag = file.delete();
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@
|
|||||||
LEFT JOIN recipe AS b ON a.food_id = b.id
|
LEFT JOIN recipe AS b ON a.food_id = b.id
|
||||||
WHERE a.date <![CDATA[ >=]]> STR_TO_DATE(#{startDate}, '%Y-%m-%d')
|
WHERE a.date <![CDATA[ >=]]> STR_TO_DATE(#{startDate}, '%Y-%m-%d')
|
||||||
AND a.date <![CDATA[ <=]]> STR_TO_DATE(#{endDate}, '%Y-%m-%d')
|
AND a.date <![CDATA[ <=]]> STR_TO_DATE(#{endDate}, '%Y-%m-%d')
|
||||||
|
AND a.person = #{user}
|
||||||
ORDER BY date DESC
|
ORDER BY date DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@@ -132,7 +133,9 @@
|
|||||||
<if test="query.category != null and query.category != ''">
|
<if test="query.category != null and query.category != ''">
|
||||||
a.category = #{query.category}
|
a.category = #{query.category}
|
||||||
</if>
|
</if>
|
||||||
|
AND a.create_by = #{user}
|
||||||
</where>
|
</where>
|
||||||
|
ORDER BY a.update_time DESC;
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="queryStats" resultType="com.cxx.food.dto.StatsDto">
|
<select id="queryStats" resultType="com.cxx.food.dto.StatsDto">
|
||||||
@@ -141,12 +144,14 @@
|
|||||||
COUNT(b.id) AS workCount
|
COUNT(b.id) AS workCount
|
||||||
FROM recipe a
|
FROM recipe a
|
||||||
LEFT JOIN record b ON a.id = b.food_id
|
LEFT JOIN record b ON a.id = b.food_id
|
||||||
|
WHERE a.create_by = #{user}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="queryRecordStats" resultType="com.cxx.food.dto.StatsChartDto">
|
<select id="queryRecordStats" resultType="com.cxx.food.dto.StatsChartDto">
|
||||||
SELECT DATE_FORMAT(date, '%Y-%m') AS name,
|
SELECT DATE_FORMAT(date, '%Y-%m') AS name,
|
||||||
COUNT(id) AS value
|
COUNT(id) AS value
|
||||||
FROM record
|
FROM record
|
||||||
|
WHERE person = #{user}
|
||||||
GROUP BY DATE_FORMAT(date, '%Y-%m')
|
GROUP BY DATE_FORMAT(date, '%Y-%m')
|
||||||
ORDER BY name DESC;
|
ORDER BY name DESC;
|
||||||
</select>
|
</select>
|
||||||
@@ -155,6 +160,7 @@
|
|||||||
SELECT category AS name,
|
SELECT category AS name,
|
||||||
COUNT(id) AS value
|
COUNT(id) AS value
|
||||||
FROM recipe
|
FROM recipe
|
||||||
|
WHERE create_by = #{user}
|
||||||
GROUP BY category
|
GROUP BY category
|
||||||
ORDER BY value DESC;
|
ORDER BY value DESC;
|
||||||
</select>
|
</select>
|
||||||
@@ -165,6 +171,7 @@
|
|||||||
FROM recipe a
|
FROM recipe a
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
record b ON a.id = b.food_id
|
record b ON a.id = b.food_id
|
||||||
|
WHERE a.create_by = #{user}
|
||||||
GROUP BY a.id, a.name
|
GROUP BY a.id, a.name
|
||||||
ORDER BY value DESC;
|
ORDER BY value DESC;
|
||||||
</select>
|
</select>
|
||||||
@@ -172,6 +179,7 @@
|
|||||||
<select id="queryCategory" resultType="string">
|
<select id="queryCategory" resultType="string">
|
||||||
SELECT DISTINCT a.category AS category
|
SELECT DISTINCT a.category AS category
|
||||||
FROM recipe a
|
FROM recipe a
|
||||||
|
WHERE a.create_by = #{user}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insertMaterial">
|
<insert id="insertMaterial">
|
||||||
|
|||||||
Reference in New Issue
Block a user