docs: add apifox
document service configuration
docs: add api document
This commit is contained in:
parent
8e1aeb7211
commit
a0c75059ba
7
.apifox-helper.properties
Normal file
7
.apifox-helper.properties
Normal file
@ -0,0 +1,7 @@
|
||||
param.ignore=@cn.wzpmc.filemanager.annotation.Address
|
||||
param.ignore=@cn.wzpmc.filemanager.annotation.AuthorizationRequired
|
||||
method.additional.header[@cn.wzpmc.filemanager.annotation.AuthorizationRequired]={name: "Authorization",value: "",description: "验证Token",required:true, example="eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImV4cCI6MTczNDA4NzM0Nn0.8EmG-u-yCLVdWtQRnfhsU5zqjIGR6vruqfI8CHba6VsBAom9gPzZz1juo1dproUItB6AXCpxMcPv1I0ggo-ZIw"}
|
||||
method.additional.header[groovy:it.args().any { params -> params.hasAnn("cn.wzpmc.filemanager.annotation.AuthorizationRequired") }]={name: "Authorization",value: "",description: "验证Token",required:true, example="eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImV4cCI6MTczNDA4NzM0Nn0.8EmG-u-yCLVdWtQRnfhsU5zqjIGR6vruqfI8CHba6VsBAom9gPzZz1juo1dproUItB6AXCpxMcPv1I0ggo-ZIw"}
|
||||
param.required=groovy:it.hasAnn("org.springframework.web.bind.annotation.RequestParam") ? it.ann("org.springframework.web.bind.annotation.RequestParam","defaultValue").equals("\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n") : true
|
||||
method.return[#response]=groovy: helper.resolveLink(it.doc("response"))
|
||||
ignore=#ignore
|
@ -5,9 +5,9 @@ import cn.wzpmc.filemanager.annotation.AuthorizationRequired;
|
||||
import cn.wzpmc.filemanager.entities.PageResult;
|
||||
import cn.wzpmc.filemanager.entities.Result;
|
||||
import cn.wzpmc.filemanager.entities.files.FolderCreateRequest;
|
||||
import cn.wzpmc.filemanager.entities.files.NamedRawFile;
|
||||
import cn.wzpmc.filemanager.entities.files.RawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.enums.FileType;
|
||||
import cn.wzpmc.filemanager.entities.files.enums.SortField;
|
||||
import cn.wzpmc.filemanager.entities.vo.FileVo;
|
||||
import cn.wzpmc.filemanager.entities.vo.FolderVo;
|
||||
import cn.wzpmc.filemanager.entities.vo.UserVo;
|
||||
@ -20,67 +20,135 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 文件操作相关接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/file")
|
||||
@RequiredArgsConstructor
|
||||
public class FileController {
|
||||
private final FileService fileService;
|
||||
|
||||
/**
|
||||
* 上传一个文件
|
||||
* @param file Multipart格式的文件对象
|
||||
* @return 文件详情
|
||||
*/
|
||||
@PutMapping("/upload")
|
||||
public Result<FileVo> simpleUpload(MultipartHttpServletRequest file, @AuthorizationRequired UserVo user, @Address String address) {
|
||||
return fileService.simpleUpload(file, user, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页获取文件
|
||||
* @param page 要获取第几页的文件
|
||||
* @param num 每一页的文件数量
|
||||
* @param folder 要获取的文件所在的文件夹
|
||||
* @param sort 文件的排序方式
|
||||
* @param reverse 是否反向排序
|
||||
* @return 分页后的文件列表
|
||||
*/
|
||||
@GetMapping("/get")
|
||||
public Result<PageResult<NamedRawFile>> getFilePager(@RequestParam long page, @RequestParam int num, @RequestParam long folder) {
|
||||
return fileService.getFilePager(page, num, folder);
|
||||
public Result<PageResult<FullRawFileObject>> getFilePager(@RequestParam long page, @RequestParam int num, @RequestParam long folder, @RequestParam(defaultValue = "TIME") SortField sort, @RequestParam(defaultValue = "false") boolean reverse) {
|
||||
return fileService.getFilePager(page, num, folder, sort, reverse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个文件夹
|
||||
* @param request 创建文件夹的相关参数
|
||||
* @return 创建的文件夹详情
|
||||
*/
|
||||
@PostMapping("/mkdir")
|
||||
public Result<FolderVo> mkdir(@RequestBody FolderCreateRequest request, @AuthorizationRequired UserVo user, @Address String address) {
|
||||
return fileService.mkdir(request, user, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个文件的简略信息
|
||||
* @param id 文件ID
|
||||
* @return 文件简略信息
|
||||
*/
|
||||
@GetMapping("/get/file")
|
||||
public Result<NamedRawFile> getFile(@RequestParam long id) {
|
||||
public Result<FullRawFileObject> getFile(@RequestParam long id) {
|
||||
return fileService.getFile(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个文件夹的简略信息
|
||||
* @param id 文件夹ID
|
||||
* @return 文件夹简略信息
|
||||
*/
|
||||
@GetMapping("/get/folder")
|
||||
public Result<NamedRawFile> getFolder(@RequestParam long id) {
|
||||
public Result<FullRawFileObject> getFolder(@RequestParam long id) {
|
||||
return fileService.getFolder(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件详细信息
|
||||
* @param id 文件ID
|
||||
* @return 文件详细信息
|
||||
*/
|
||||
@GetMapping("/detail/file")
|
||||
public Result<FileVo> getFileDetail(@RequestParam long id) {
|
||||
return fileService.getFileDetail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个文件/文件夹
|
||||
* @param id 文件/文件夹ID
|
||||
* @param type 目标为文件/文件夹
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@DeleteMapping("/rm")
|
||||
public Result<Void> delete(@RequestParam long id, @RequestParam FileType type, @AuthorizationRequired UserVo user, @Address String address) {
|
||||
return fileService.delete(id, type, user, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件下载链接
|
||||
* @param id 文件ID
|
||||
* @return 文件下载链接ID
|
||||
*/
|
||||
@GetMapping("/link")
|
||||
public Result<String> getFileLink(@RequestParam long id, @Address String address, HttpServletRequest request) {
|
||||
return fileService.getFileLink(id, address, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过下载文件ID下载文件
|
||||
* @param id 下载ID
|
||||
* @see #getFileLink(long, String, HttpServletRequest)
|
||||
*/
|
||||
@GetMapping("/download/{id}")
|
||||
public void downloadFile(@PathVariable String id, @RequestHeader(value = "Range", defaultValue = "null") String range, HttpServletResponse response) {
|
||||
fileService.downloadFile(id, range, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享文件
|
||||
* @deprecated
|
||||
*/
|
||||
@GetMapping("/share")
|
||||
public Result<String> shareFile(@RequestParam Long id, @RequestParam(defaultValue = "9999-12-31") Date lastCouldDownloadTime, @RequestParam(defaultValue = "-1") int maxDownloadCount) {
|
||||
return fileService.shareFile(id, lastCouldDownloadTime, maxDownloadCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过路径解析文件信息
|
||||
* @param path 需要解析的文件路径
|
||||
* @return 文件粗略信息
|
||||
*/
|
||||
@GetMapping("/path/resolve")
|
||||
public Result<RawFileObject> resolveFileDetail(@RequestParam String path) {
|
||||
public Result<FullRawFileObject> resolveFileDetail(@RequestParam String path) {
|
||||
return fileService.resolveFileDetail(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过文件ID获取文件路径
|
||||
* @param id 文件ID
|
||||
* @param type 目标文件为文件/文件夹
|
||||
* @return 文件的路径
|
||||
*/
|
||||
@GetMapping("/path/{id}")
|
||||
public Result<String> findFilePathById(@PathVariable("id") long id, @RequestParam(value = "type", defaultValue = "FILE") FileType type) {
|
||||
return type.equals(FileType.FILE) ? fileService.findFilePathById(id) : fileService.findFolderPathById(id);
|
||||
|
@ -9,39 +9,63 @@ import cn.wzpmc.filemanager.entities.user.enums.Auth;
|
||||
import cn.wzpmc.filemanager.entities.vo.UserVo;
|
||||
import cn.wzpmc.filemanager.service.UserService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 用户相关接口
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
@RequiredArgsConstructor
|
||||
public class UserController {
|
||||
private final UserService userService;
|
||||
|
||||
@Autowired
|
||||
public UserController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录接口
|
||||
* @param loginRequest 登录请求体
|
||||
* @response {@link Result<UserVo>}
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public void login(@RequestBody UserLoginRequest loginRequest, HttpServletResponse response, @Address String address) {
|
||||
userService.login(loginRequest, response, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册接口
|
||||
* @param registerRequest 注册请求体
|
||||
* @response {@link Result<UserVo>}
|
||||
*/
|
||||
@PutMapping("/register")
|
||||
public void register(@RequestBody UserRegisterRequest registerRequest, HttpServletResponse response, @Address String address) {
|
||||
userService.register(registerRequest, response, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员用户生成邀请码接口
|
||||
* @return 邀请码
|
||||
*/
|
||||
@GetMapping("/invite")
|
||||
public Result<String> invite(@AuthorizationRequired(level = Auth.admin) UserVo userVo, @Address String address) {
|
||||
return userService.invite(userVo, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息接口
|
||||
* @return 用户信息
|
||||
*/
|
||||
@GetMapping("/info")
|
||||
public Result<UserVo> getUserInfo(@AuthorizationRequired UserVo user) {
|
||||
return Result.success(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定用户信息接口
|
||||
* @param id 用户ID
|
||||
* @return 该ID的用户信息
|
||||
*/
|
||||
@GetMapping("/info/{id}")
|
||||
public Result<UserVo> getUser(@PathVariable Long id) {
|
||||
return userService.getUserInformation(id);
|
||||
|
@ -10,6 +10,12 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@JSONCompiled
|
||||
public class PageResult<T> {
|
||||
/**
|
||||
* 总行数
|
||||
*/
|
||||
private long total;
|
||||
/**
|
||||
* 当前页数据
|
||||
*/
|
||||
private List<T> data;
|
||||
}
|
||||
|
@ -16,89 +16,121 @@ import java.nio.charset.StandardCharsets;
|
||||
@Data
|
||||
@JSONCompiled
|
||||
public class Result<T> {
|
||||
/**
|
||||
* 请求的响应码
|
||||
*/
|
||||
private int status;
|
||||
/**
|
||||
* 请求的响应信息
|
||||
*/
|
||||
private String msg;
|
||||
/**
|
||||
* 请求的响应数据
|
||||
*/
|
||||
private T data;
|
||||
/**
|
||||
* 请求生成的时间戳
|
||||
*/
|
||||
private long timestamp;
|
||||
|
||||
protected Result() {
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected Result(int status, String msg, T data) {
|
||||
this();
|
||||
this.status = status;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
protected Result(HttpStatus status) {
|
||||
this();
|
||||
this.status = status.value();
|
||||
this.msg = status.getReasonPhrase();
|
||||
}
|
||||
|
||||
protected Result(HttpStatus status, String msg) {
|
||||
this(status);
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
protected Result(HttpStatus status, T data) {
|
||||
this(status);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
protected Result(HttpStatus status, String msg, T data) {
|
||||
this(status, msg);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public static <T> Result<T> success() {
|
||||
return new Result<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(String msg) {
|
||||
return new Result<>(HttpStatus.OK, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(T data) {
|
||||
return new Result<>(HttpStatus.OK, data);
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(String msg, T data) {
|
||||
return new Result<>(HttpStatus.OK, msg, data);
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed() {
|
||||
return new Result<>(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed(String msg) {
|
||||
return new Result<>(HttpStatus.FORBIDDEN, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed(HttpStatus status) {
|
||||
return new Result<>(status);
|
||||
}
|
||||
|
||||
public static <T> Result<T> failed(HttpStatus status, String msg) {
|
||||
return new Result<>(status, msg);
|
||||
}
|
||||
|
||||
public static <T> Result<T> create() {
|
||||
return new Result<>();
|
||||
}
|
||||
|
||||
public Result<T> status(int status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> status(HttpStatus status) {
|
||||
this.status = status.value();
|
||||
this.msg = status.getReasonPhrase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> msg(String msg) {
|
||||
this.msg = msg;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result<T> data(T data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void writeToResponse(HttpServletResponse response){
|
||||
public void writeToResponse(HttpServletResponse response) {
|
||||
response.addHeader("Content-Type", "application/json; charset=utf-8");
|
||||
try(ServletOutputStream outputStream = response.getOutputStream()){
|
||||
try (ServletOutputStream outputStream = response.getOutputStream()) {
|
||||
writeToOutputStream(outputStream);
|
||||
} catch (IOException e) {
|
||||
log.trace("写出到流失败,", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToOutputStream(OutputStream stream) throws IOException {
|
||||
stream.write(JSON.toJSONString(this).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
@ -6,6 +6,12 @@ import lombok.Data;
|
||||
@Data
|
||||
@JSONCompiled
|
||||
public class FolderCreateRequest {
|
||||
/**
|
||||
* 父文件夹ID
|
||||
*/
|
||||
private long parent;
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String name;
|
||||
}
|
||||
|
@ -1,16 +1,25 @@
|
||||
package cn.wzpmc.filemanager.entities.files;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONCompiled;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("raw_file")
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@JSONCompiled
|
||||
public class NamedRawFile extends RawFileObject {
|
||||
public class FullRawFileObject extends RawFileObject {
|
||||
/**
|
||||
* 文件所有者名称
|
||||
*/
|
||||
private String ownerName;
|
||||
/**
|
||||
* 文件下载次数
|
||||
*/
|
||||
private long downCount;
|
||||
}
|
@ -15,13 +15,37 @@ import java.util.Date;
|
||||
@NoArgsConstructor
|
||||
@JSONCompiled
|
||||
public class RawFileObject {
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
private long id;
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 文件扩展名(文件夹为null)
|
||||
*/
|
||||
private String ext;
|
||||
/**
|
||||
* 文件大小(文件夹为-1)
|
||||
*/
|
||||
private long size;
|
||||
/**
|
||||
* 文件所有者
|
||||
*/
|
||||
private long owner;
|
||||
/**
|
||||
* 父文件夹ID
|
||||
*/
|
||||
private long parent;
|
||||
/**
|
||||
* 文件上传时间
|
||||
*/
|
||||
private Date time;
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
private FileType type;
|
||||
|
||||
public static RawFileObject of(FileVo file) {
|
||||
|
@ -4,5 +4,12 @@ import com.alibaba.fastjson2.annotation.JSONCompiled;
|
||||
|
||||
@JSONCompiled
|
||||
public enum FileType {
|
||||
FILE, FOLDER
|
||||
/**
|
||||
* 文件
|
||||
*/
|
||||
FILE,
|
||||
/**
|
||||
* 文件夹
|
||||
*/
|
||||
FOLDER
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cn.wzpmc.filemanager.entities.files.enums;
|
||||
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum SortField {
|
||||
/**
|
||||
* 通过ID排序(默认)
|
||||
*/
|
||||
ID(FULL_RAW_FILE_OBJECT.ID),
|
||||
/**
|
||||
* 通过文件夹排序
|
||||
*/
|
||||
NAME(FULL_RAW_FILE_OBJECT.NAME),
|
||||
/**
|
||||
* 通过文件扩展名排序
|
||||
*/
|
||||
EXT(FULL_RAW_FILE_OBJECT.EXT),
|
||||
/**
|
||||
* 通过文件上传时间排序
|
||||
*/
|
||||
TIME(FULL_RAW_FILE_OBJECT.TIME),
|
||||
/**
|
||||
* 通过文件上传者排序
|
||||
*/
|
||||
UPLOADER(FULL_RAW_FILE_OBJECT.OWNER),
|
||||
/**
|
||||
* 通过文件下载次数排序
|
||||
*/
|
||||
DOWNLOAD_COUNT(FULL_RAW_FILE_OBJECT.DOWN_COUNT);
|
||||
public final QueryColumn column;
|
||||
}
|
@ -4,5 +4,36 @@ import com.alibaba.fastjson2.annotation.JSONCompiled;
|
||||
|
||||
@JSONCompiled
|
||||
public enum Actions {
|
||||
UPLOAD, DELETE, ACCESS, DOWNLOAD, SEARCH, LOGIN, INVITE, REGISTER
|
||||
/**
|
||||
* 文件上传事件
|
||||
*/
|
||||
UPLOAD,
|
||||
/**
|
||||
* 文件删除事件
|
||||
*/
|
||||
DELETE,
|
||||
/**
|
||||
* 访问页面事件
|
||||
*/
|
||||
ACCESS,
|
||||
/**
|
||||
* 文件下载事件
|
||||
*/
|
||||
DOWNLOAD,
|
||||
/**
|
||||
* 搜索文件事件
|
||||
*/
|
||||
SEARCH,
|
||||
/**
|
||||
* 登录事件
|
||||
*/
|
||||
LOGIN,
|
||||
/**
|
||||
* 获取邀请码事件
|
||||
*/
|
||||
INVITE,
|
||||
/**
|
||||
* 注册事件
|
||||
*/
|
||||
REGISTER
|
||||
}
|
@ -6,6 +6,12 @@ import lombok.Data;
|
||||
@Data
|
||||
@JSONCompiled
|
||||
public class UserLoginRequest {
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码(通过MD5摘要)
|
||||
*/
|
||||
private String password;
|
||||
}
|
@ -7,8 +7,20 @@ import lombok.Data;
|
||||
@Data
|
||||
@JSONCompiled
|
||||
public class UserRegisterRequest {
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* 密码(经过MD5摘要)
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private Auth auth;
|
||||
/**
|
||||
* 邀请码(当作为admin(管理员)注册时需填写,若作为user(普通用户)注册时无需)
|
||||
*/
|
||||
private String inviteCode;
|
||||
}
|
@ -7,7 +7,14 @@ import lombok.AllArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
@JSONCompiled
|
||||
public enum Auth {
|
||||
admin(1, "admin"), user(0, "user");
|
||||
/**
|
||||
* 管理员
|
||||
*/
|
||||
admin(1, "admin"),
|
||||
/**
|
||||
* 普通用户
|
||||
*/
|
||||
user(0, "user");
|
||||
public final int value;
|
||||
@EnumValue
|
||||
public final String name;
|
||||
|
@ -14,15 +14,42 @@ import java.util.Date;
|
||||
@Data
|
||||
@JSONCompiled
|
||||
public class FileVo implements Serializable {
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private long id;
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 文件扩展名
|
||||
*/
|
||||
private String ext;
|
||||
/**
|
||||
* 文件的MIME类型
|
||||
*/
|
||||
private String mime;
|
||||
/**
|
||||
* 文件的Sha512哈希值
|
||||
*/
|
||||
private String hash;
|
||||
/**
|
||||
* 文件的上传者ID
|
||||
*/
|
||||
private long uploader;
|
||||
/**
|
||||
* 文件的父文件夹ID
|
||||
*/
|
||||
private long folder;
|
||||
/**
|
||||
* 文件的大小 (bytes)
|
||||
*/
|
||||
private long size;
|
||||
/**
|
||||
* 文件的上传时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private Date uploadTime;
|
||||
|
||||
|
@ -13,11 +13,26 @@ import java.util.Date;
|
||||
@Data
|
||||
@JSONCompiled
|
||||
public class FolderVo {
|
||||
/**
|
||||
* 文件夹ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private long id;
|
||||
/**
|
||||
* 文件夹名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 文件夹的父文件夹ID
|
||||
*/
|
||||
private long parent;
|
||||
/**
|
||||
* 文件夹的创建者
|
||||
*/
|
||||
private long creator;
|
||||
/**
|
||||
* 文件夹的创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private Date createTime;
|
||||
|
||||
|
@ -6,6 +6,7 @@ import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -14,13 +15,32 @@ import java.util.Date;
|
||||
@NoArgsConstructor
|
||||
@JSONCompiled
|
||||
public class StatisticsVo {
|
||||
/***
|
||||
* 操作者(可能为空)
|
||||
*/
|
||||
@Nullable
|
||||
private Long actor;
|
||||
/**
|
||||
* 具体操作
|
||||
*/
|
||||
private Actions action;
|
||||
/**
|
||||
* 操作参数(一般为JSON字符串)
|
||||
*/
|
||||
private String params;
|
||||
/**
|
||||
* 操作时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private Date time;
|
||||
/**
|
||||
* 若为下载操作时的下载文件ID
|
||||
* @ignore
|
||||
*/
|
||||
@Column(value = "download_file_id", ignore = true)
|
||||
private Integer downloadFileId;
|
||||
|
||||
public StatisticsVo(Long actor, Actions action, String params) {
|
||||
public StatisticsVo(@Nullable Long actor, Actions action, String params) {
|
||||
this.actor = actor;
|
||||
this.action = action;
|
||||
this.params = params;
|
||||
|
@ -14,28 +14,50 @@ import lombok.Data;
|
||||
@AllArgsConstructor
|
||||
@JSONCompiled
|
||||
public class UserVo {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private long id;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 用户密码
|
||||
* @ignore
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private Auth auth;
|
||||
/**
|
||||
* 用户是否被封禁
|
||||
* `尽管封了你也看不到就是了`
|
||||
*/
|
||||
@Column(isLogicDelete = true, onInsertValue = "0")
|
||||
private boolean banned;
|
||||
|
||||
public UserVo(String name, String password, Auth auth) {
|
||||
this.name = name;
|
||||
this.password = password;
|
||||
this.auth = auth;
|
||||
}
|
||||
private UserVo(long id, String name, Auth auth){
|
||||
|
||||
private UserVo(long id, String name, Auth auth) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public UserVo(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void clearPassword() {
|
||||
this.setPassword(null);
|
||||
}
|
||||
|
||||
public static final UserVo CONSOLE = new UserVo(0L, "CONSOLE", Auth.admin);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package cn.wzpmc.filemanager.entities.vo.table.custom;
|
||||
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
|
||||
public class StatisticsVoTableDef extends cn.wzpmc.filemanager.entities.vo.table.StatisticsVoTableDef {
|
||||
public static final StatisticsVoTableDef STATISTICS_VO_EXT = new StatisticsVoTableDef();
|
||||
public final QueryColumn DOWNLOAD_FILE_ID = new QueryColumn(this, "download_file_id");
|
||||
}
|
@ -20,6 +20,7 @@ public class StartEventListener {
|
||||
initializationMapper.createStatisticsTable();
|
||||
initializationMapper.createFolderTable();
|
||||
initializationMapper.createFileTable();
|
||||
initializationMapper.createRawFileView();
|
||||
//开启审计功能
|
||||
AuditManager.setAuditEnable(true);
|
||||
MessageCollector collector = new ConsoleMessageCollector();
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.wzpmc.filemanager.interfaces;
|
||||
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.RawFileObject;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
@ -9,5 +10,5 @@ public interface FilePathService {
|
||||
String getFilePath(@NonNull RawFileObject file);
|
||||
|
||||
@Nullable
|
||||
RawFileObject resolveFile(@NonNull String[] path);
|
||||
FullRawFileObject resolveFile(@NonNull String[] path);
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package cn.wzpmc.filemanager.interfaces.impl;
|
||||
|
||||
import cn.wzpmc.filemanager.entities.files.RawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import cn.wzpmc.filemanager.mapper.FileMapper;
|
||||
import cn.wzpmc.filemanager.mapper.FolderMapper;
|
||||
import cn.wzpmc.filemanager.mapper.RawFileMapper;
|
||||
import com.mybatisflex.core.query.QueryCondition;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
@ -13,8 +15,7 @@ import org.springframework.stereotype.Component;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FileVoTableDef.FILE_VO;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FolderVoTableDef.FOLDER_VO;
|
||||
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
|
||||
|
||||
@Component
|
||||
@Primary
|
||||
@ -22,16 +23,18 @@ import static cn.wzpmc.filemanager.entities.vo.table.FolderVoTableDef.FOLDER_VO;
|
||||
public class ComplexResolver extends SimplePathResolver {
|
||||
private final ReverseResolver reverseResolver;
|
||||
private final SimpleResolver simpleResolver;
|
||||
private final RawFileMapper rawFileMapper;
|
||||
@Autowired
|
||||
public ComplexResolver(FileMapper fileMapper, FolderMapper folderMapper, ReverseResolver reverseResolver, SimpleResolver simpleResolver) {
|
||||
public ComplexResolver(FileMapper fileMapper, FolderMapper folderMapper, ReverseResolver reverseResolver, SimpleResolver simpleResolver, RawFileMapper rawFileMapper) {
|
||||
super(fileMapper, folderMapper);
|
||||
this.reverseResolver = reverseResolver;
|
||||
this.simpleResolver = simpleResolver;
|
||||
this.rawFileMapper = rawFileMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public RawFileObject resolveFile(@NonNull String[] path) {
|
||||
public FullRawFileObject resolveFile(@NonNull String[] path) {
|
||||
String strPath = Arrays.toString(path);
|
||||
String targetFileName = path[path.length - 1];
|
||||
int lastDotIndex = targetFileName.lastIndexOf('.');
|
||||
@ -42,17 +45,21 @@ public class ComplexResolver extends SimplePathResolver {
|
||||
ext = targetFileName.substring(lastDotIndex + 1);
|
||||
}
|
||||
long start = new Date().getTime();
|
||||
long totalRawFileCount = this.fileMapper.selectCountByCondition(FILE_VO.NAME.eq(name).and(FILE_VO.EXT.eq(ext))) + this.folderMapper.selectCountByCondition(FOLDER_VO.NAME.eq(name));
|
||||
QueryCondition extCondition = FULL_RAW_FILE_OBJECT.EXT.eq(ext);
|
||||
if (ext.isEmpty()) {
|
||||
extCondition = extCondition.or(FULL_RAW_FILE_OBJECT.EXT.isNull());
|
||||
}
|
||||
long totalRawFileCount = this.rawFileMapper.selectCountByCondition(FULL_RAW_FILE_OBJECT.NAME.eq(name).and(extCondition));
|
||||
if (totalRawFileCount == 0) return null;
|
||||
if (totalRawFileCount > path.length) {
|
||||
log.info("use simple resolver to solve path with {}", strPath);
|
||||
RawFileObject rawFileObject = simpleResolver.resolveFile(path);
|
||||
FullRawFileObject rawFileObject = simpleResolver.resolveFile(path);
|
||||
long end = new Date().getTime();
|
||||
log.info("solve path {} cost {}ms", strPath, end - start);
|
||||
return rawFileObject;
|
||||
}
|
||||
log.info("use reverse resolver to solve path with {}", strPath);
|
||||
RawFileObject rawFileObject = reverseResolver.resolveFile(path);
|
||||
FullRawFileObject rawFileObject = reverseResolver.resolveFile(path);
|
||||
long end = new Date().getTime();
|
||||
log.info("solve path {} cost {}ms", strPath, end - start);
|
||||
return rawFileObject;
|
||||
|
@ -1,29 +1,34 @@
|
||||
package cn.wzpmc.filemanager.interfaces.impl;
|
||||
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.RawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.vo.FolderVo;
|
||||
import cn.wzpmc.filemanager.mapper.FileMapper;
|
||||
import cn.wzpmc.filemanager.mapper.FolderMapper;
|
||||
import cn.wzpmc.filemanager.mapper.RawFileMapper;
|
||||
import com.mybatisflex.core.query.QueryCondition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FileVoTableDef.FILE_VO;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FolderVoTableDef.FOLDER_VO;
|
||||
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
|
||||
|
||||
@Component
|
||||
public class ReverseResolver extends SimplePathResolver {
|
||||
public ReverseResolver(FileMapper fileMapper, FolderMapper folderMapper) {
|
||||
private final RawFileMapper rawFileMapper;
|
||||
@Autowired
|
||||
public ReverseResolver(FileMapper fileMapper, FolderMapper folderMapper, RawFileMapper rawFileMapper) {
|
||||
super(fileMapper, folderMapper);
|
||||
this.rawFileMapper = rawFileMapper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RawFileObject resolveFile(@NonNull String[] path) {
|
||||
public FullRawFileObject resolveFile(@NonNull String[] path) {
|
||||
List<String> pathList = removeEmptyPath(path);
|
||||
String targetFileName = pathList.get(pathList.size() - 1);
|
||||
int lastDotIndex = targetFileName.lastIndexOf('.');
|
||||
@ -33,13 +38,15 @@ public class ReverseResolver extends SimplePathResolver {
|
||||
name = targetFileName.substring(0, lastDotIndex);
|
||||
ext = targetFileName.substring(lastDotIndex + 1);
|
||||
}
|
||||
List<RawFileObject> rawFileObjects = new ArrayList<>();
|
||||
fileMapper.selectListByCondition(FILE_VO.NAME.eq(name).and(FILE_VO.EXT.eq(ext))).stream().map(RawFileObject::of).forEach(rawFileObjects::add);
|
||||
folderMapper.selectListByCondition(FOLDER_VO.NAME.eq(name)).stream().map(RawFileObject::of).forEach(rawFileObjects::add);
|
||||
QueryCondition extCondition = FULL_RAW_FILE_OBJECT.EXT.eq(ext);
|
||||
if (ext.isEmpty()) {
|
||||
extCondition = extCondition.or(FULL_RAW_FILE_OBJECT.EXT.isNull());
|
||||
}
|
||||
List<FullRawFileObject> rawFileObjects = this.rawFileMapper.selectListByCondition(FULL_RAW_FILE_OBJECT.NAME.eq(name).and(extCondition));
|
||||
if (rawFileObjects.isEmpty()) return null;
|
||||
if (rawFileObjects.size() == 1) return rawFileObjects.get(0);
|
||||
List<Long> possibleParents = rawFileObjects.stream().map(RawFileObject::getParent).toList();
|
||||
Optional<RawFileObject> inRoot = rawFileObjects.stream().filter(e -> e.getParent() == -1).findFirst();
|
||||
Optional<FullRawFileObject> inRoot = rawFileObjects.stream().filter(e -> e.getParent() == -1).findFirst();
|
||||
if (inRoot.isPresent()) {
|
||||
if (pathList.size() <= 1) {
|
||||
return inRoot.get();
|
||||
@ -48,7 +55,7 @@ public class ReverseResolver extends SimplePathResolver {
|
||||
List<FolderVo> folderVos = folderMapper.selectListByIds(possibleParents);
|
||||
FolderVo parent = reverseFindFileParent(folderVos, pathList.subList(0, pathList.size() - 1));
|
||||
if (parent == null) return null;
|
||||
Optional<RawFileObject> first = rawFileObjects.stream().filter(e -> e.getParent() == parent.getId()).findFirst();
|
||||
Optional<FullRawFileObject> first = rawFileObjects.stream().filter(e -> e.getParent() == parent.getId()).findFirst();
|
||||
return first.orElse(null);
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
package cn.wzpmc.filemanager.interfaces.impl;
|
||||
|
||||
import cn.wzpmc.filemanager.entities.files.RawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.vo.FileVo;
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.enums.FileType;
|
||||
import cn.wzpmc.filemanager.entities.vo.FolderVo;
|
||||
import cn.wzpmc.filemanager.mapper.FileMapper;
|
||||
import cn.wzpmc.filemanager.mapper.FolderMapper;
|
||||
import cn.wzpmc.filemanager.mapper.RawFileMapper;
|
||||
import com.mybatisflex.core.query.QueryCondition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
@ -12,23 +14,26 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FileVoTableDef.FILE_VO;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FolderVoTableDef.FOLDER_VO;
|
||||
|
||||
@Component
|
||||
public class SimpleResolver extends SimplePathResolver {
|
||||
private final RawFileMapper rawFileMapper;
|
||||
@Autowired
|
||||
public SimpleResolver(FileMapper fileMapper, FolderMapper folderMapper) {
|
||||
public SimpleResolver(FileMapper fileMapper, FolderMapper folderMapper, RawFileMapper rawFileMapper) {
|
||||
super(fileMapper, folderMapper);
|
||||
this.rawFileMapper = rawFileMapper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RawFileObject resolveFile(@NonNull String[] path) {
|
||||
public FullRawFileObject resolveFile(@NonNull String[] path) {
|
||||
return resolveFile(removeEmptyPath(path), -1);
|
||||
}
|
||||
|
||||
private RawFileObject resolveFile(List<String> path, long parentId) {
|
||||
private FullRawFileObject resolveFile(List<String> path, long parentId) {
|
||||
String currentLayerName = path.get(0);
|
||||
if (path.size() == 1) {
|
||||
int lastDotIndex = currentLayerName.lastIndexOf('.');
|
||||
@ -38,11 +43,19 @@ public class SimpleResolver extends SimplePathResolver {
|
||||
name = currentLayerName.substring(0, lastDotIndex);
|
||||
ext = currentLayerName.substring(lastDotIndex + 1);
|
||||
}
|
||||
FileVo file = fileMapper.selectOneByCondition(FILE_VO.NAME.eq(name).and(FILE_VO.EXT.eq(ext)).and(FILE_VO.FOLDER.eq(parentId)));
|
||||
if (file != null) {
|
||||
return RawFileObject.of(file);
|
||||
QueryCondition extCondition = FULL_RAW_FILE_OBJECT.EXT.eq(ext);
|
||||
if (ext.isEmpty()) {
|
||||
extCondition = extCondition.or(FULL_RAW_FILE_OBJECT.EXT.isNull());
|
||||
}
|
||||
return RawFileObject.of(folderMapper.selectOneByCondition(FOLDER_VO.NAME.eq(name).and(FOLDER_VO.PARENT.eq(parentId))));
|
||||
List<FullRawFileObject> files = rawFileMapper.selectListByCondition(FULL_RAW_FILE_OBJECT.NAME.eq(name).and(extCondition).and(FILE_VO.FOLDER.eq(parentId)));
|
||||
int size = files.size();
|
||||
if (size == 0) {
|
||||
return null;
|
||||
}
|
||||
if (size == 1) {
|
||||
return files.get(0);
|
||||
}
|
||||
return files.stream().filter(e -> e.getType().equals(FileType.FILE)).findFirst().orElse(null);
|
||||
}
|
||||
FolderVo folderVo = folderMapper.selectOneByCondition(FOLDER_VO.NAME.eq(currentLayerName).and(FOLDER_VO.PARENT.eq(parentId)));
|
||||
if (folderVo == null) {
|
||||
|
@ -8,4 +8,5 @@ public interface InitializationMapper {
|
||||
void createFolderTable();
|
||||
void createStatisticsTable();
|
||||
void createUserTable();
|
||||
void createRawFileView();
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
package cn.wzpmc.filemanager.mapper;
|
||||
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface RawFileMapper extends BaseMapper<FullRawFileObject> {
|
||||
}
|
@ -4,9 +4,10 @@ import cn.wzpmc.filemanager.config.FileManagerProperties;
|
||||
import cn.wzpmc.filemanager.entities.PageResult;
|
||||
import cn.wzpmc.filemanager.entities.Result;
|
||||
import cn.wzpmc.filemanager.entities.files.FolderCreateRequest;
|
||||
import cn.wzpmc.filemanager.entities.files.NamedRawFile;
|
||||
import cn.wzpmc.filemanager.entities.files.FullRawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.RawFileObject;
|
||||
import cn.wzpmc.filemanager.entities.files.enums.FileType;
|
||||
import cn.wzpmc.filemanager.entities.files.enums.SortField;
|
||||
import cn.wzpmc.filemanager.entities.statistics.enums.Actions;
|
||||
import cn.wzpmc.filemanager.entities.user.enums.Auth;
|
||||
import cn.wzpmc.filemanager.entities.vo.FileVo;
|
||||
@ -15,6 +16,7 @@ import cn.wzpmc.filemanager.entities.vo.UserVo;
|
||||
import cn.wzpmc.filemanager.interfaces.FilePathService;
|
||||
import cn.wzpmc.filemanager.mapper.FileMapper;
|
||||
import cn.wzpmc.filemanager.mapper.FolderMapper;
|
||||
import cn.wzpmc.filemanager.mapper.RawFileMapper;
|
||||
import cn.wzpmc.filemanager.utils.JwtUtils;
|
||||
import cn.wzpmc.filemanager.utils.RandomUtils;
|
||||
import cn.wzpmc.filemanager.utils.SizeStatisticsDigestInputStream;
|
||||
@ -51,6 +53,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static cn.wzpmc.filemanager.entities.files.table.FullRawFileObjectTableDef.FULL_RAW_FILE_OBJECT;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FileVoTableDef.FILE_VO;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.FolderVoTableDef.FOLDER_VO;
|
||||
import static cn.wzpmc.filemanager.entities.vo.table.UserVoTableDef.USER_VO;
|
||||
@ -62,6 +65,7 @@ import static com.mybatisflex.core.query.QueryMethods.*;
|
||||
public class FileService {
|
||||
private final FileMapper fileMapper;
|
||||
private final FolderMapper folderMapper;
|
||||
private final RawFileMapper rawFileMapper;
|
||||
private final RandomUtils randomUtils;
|
||||
private final FileManagerProperties properties;
|
||||
private final StatisticsService statisticsService;
|
||||
@ -197,19 +201,14 @@ public class FileService {
|
||||
return folderParams;
|
||||
}
|
||||
|
||||
public Result<PageResult<NamedRawFile>> getFilePager(long page, int num, long folder) {
|
||||
QueryWrapper folderQueryWrapper = queryRawFolderWithOwnerName().where(FOLDER_VO.PARENT.eq(folder));
|
||||
QueryWrapper fileQueryWrapper = queryRawFileWithOwnerName().where(FILE_VO.FOLDER.eq(folder));
|
||||
QueryWrapper queryWrapper = fileQueryWrapper.unionAll(folderQueryWrapper)
|
||||
.orderBy(
|
||||
column("time").
|
||||
asc(),
|
||||
column("id").
|
||||
asc()
|
||||
);
|
||||
long totalCount = fileMapper.selectCountByCondition(FILE_VO.FOLDER.eq(folder)) + folderMapper.selectCountByCondition(FOLDER_VO.PARENT.eq(folder));
|
||||
Page<NamedRawFile> paginate = fileMapper.paginateAs(page, num, totalCount, queryWrapper, NamedRawFile.class);
|
||||
PageResult<NamedRawFile> result = new PageResult<>(paginate.getTotalRow(), paginate.getRecords());
|
||||
public Result<PageResult<FullRawFileObject>> getFilePager(long page, int num, long folder, SortField sort, boolean reverse) {
|
||||
QueryWrapper from = QueryWrapper.create().select(FULL_RAW_FILE_OBJECT.ALL_COLUMNS).from(FULL_RAW_FILE_OBJECT).where(FULL_RAW_FILE_OBJECT.PARENT.eq(folder));
|
||||
if (sort != SortField.ID) {
|
||||
from = from.orderBy(sort.column, reverse);
|
||||
}
|
||||
from = from.orderBy(FULL_RAW_FILE_OBJECT.ID, reverse);
|
||||
Page<FullRawFileObject> paginate = rawFileMapper.paginate(page, num, from);
|
||||
PageResult<FullRawFileObject> result = new PageResult<>(paginate.getTotalRow(), paginate.getRecords());
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
@ -327,7 +326,7 @@ public class FileService {
|
||||
FileVo fileVo = fileMapper.selectOneById(id);
|
||||
long fileId = fileVo.getId();
|
||||
String identify = ID_ADDR_PREFIX + fileId + address;
|
||||
String link = idAddrLinkMapper.opsForValue().get(identify);
|
||||
String link = null;// idAddrLinkMapper.opsForValue().get(identify);
|
||||
if (link == null) {
|
||||
link = randomUtils.generatorRandomFileName(8);
|
||||
String authorization = request.getHeader("Authorization");
|
||||
@ -353,9 +352,9 @@ public class FileService {
|
||||
return Result.success(linkName);
|
||||
}
|
||||
|
||||
public Result<RawFileObject> resolveFileDetail(String path) {
|
||||
public Result<FullRawFileObject> resolveFileDetail(String path) {
|
||||
String[] split = path.split(PATH_SEPARATOR);
|
||||
RawFileObject fileObj = pathService.resolveFile(split);
|
||||
FullRawFileObject fileObj = pathService.resolveFile(split);
|
||||
if (fileObj == null) {
|
||||
return Result.failed(HttpStatus.NOT_FOUND, "文件不存在!");
|
||||
}
|
||||
@ -378,16 +377,16 @@ public class FileService {
|
||||
return Result.success("成功", pathService.getFilePath(RawFileObject.of(folderVo)));
|
||||
}
|
||||
|
||||
public Result<NamedRawFile> getFile(long id) {
|
||||
NamedRawFile fileVo = this.fileMapper.selectOneByQueryAs(queryRawFileWithOwnerName().where(FILE_VO.ID.eq(id)), NamedRawFile.class);
|
||||
public Result<FullRawFileObject> getFile(long id) {
|
||||
FullRawFileObject fileVo = this.rawFileMapper.selectOneByCondition(FULL_RAW_FILE_OBJECT.TYPE.eq(FileType.FILE).and(FULL_RAW_FILE_OBJECT.ID.eq(id)));
|
||||
if (fileVo == null) {
|
||||
return Result.failed(HttpStatus.NOT_FOUND, "未知文件");
|
||||
}
|
||||
return Result.success(fileVo);
|
||||
}
|
||||
|
||||
public Result<NamedRawFile> getFolder(long id) {
|
||||
NamedRawFile fileVo = this.folderMapper.selectOneByQueryAs(queryRawFolderWithOwnerName().where(FOLDER_VO.ID.eq(id)), NamedRawFile.class);
|
||||
public Result<FullRawFileObject> getFolder(long id) {
|
||||
FullRawFileObject fileVo = this.rawFileMapper.selectOneByCondition(FULL_RAW_FILE_OBJECT.TYPE.eq(FileType.FOLDER).and(FULL_RAW_FILE_OBJECT.ID.eq(id)));
|
||||
if (fileVo == null) {
|
||||
return Result.failed(HttpStatus.NOT_FOUND, "未知文件");
|
||||
}
|
||||
|
20
src/main/java/cn/wzpmc/filemanager/utils/MyQueryMethods.java
Normal file
20
src/main/java/cn/wzpmc/filemanager/utils/MyQueryMethods.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cn.wzpmc.filemanager.utils;
|
||||
|
||||
import com.mybatisflex.core.query.FunctionQueryColumn;
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
|
||||
import static com.mybatisflex.core.query.QueryMethods.string;
|
||||
|
||||
public class MyQueryMethods {
|
||||
public static QueryColumn jsonReadColumn(QueryColumn column, String express) {
|
||||
String[] dotedSplit = express.split("\\.");
|
||||
StringBuilder sb = new StringBuilder("$");
|
||||
for (String s : dotedSplit) {
|
||||
sb.append('.');
|
||||
sb.append('"');
|
||||
sb.append(s);
|
||||
sb.append('"');
|
||||
}
|
||||
return new FunctionQueryColumn("JSON_EXTRACT", column, string(sb.toString()));
|
||||
}
|
||||
}
|
@ -44,18 +44,19 @@
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='文件夹';
|
||||
</insert>
|
||||
<insert id="createStatisticsTable">
|
||||
CREATE TABLE IF NOT EXISTS `statistics`
|
||||
(
|
||||
CREATE TABLE IF NOT EXISTS `statistics` (
|
||||
`actor` int DEFAULT NULL COMMENT '操作者',
|
||||
`action` enum ('UPLOAD','DELETE','ACCESS','DOWNLOAD','SEARCH','LOGIN','INVITE','REGISTER') COLLATE utf8mb4_general_ci NOT NULL COMMENT '所做的操作',
|
||||
`action` enum('UPLOAD','DELETE','ACCESS','DOWNLOAD','SEARCH','LOGIN','INVITE','REGISTER') COLLATE
|
||||
utf8mb4_general_ci NOT NULL COMMENT '所做的操作',
|
||||
`params` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作的参数(在ACCESS操作中为空)',
|
||||
`time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作的时间',
|
||||
`download_file_id` int GENERATED ALWAYS AS (if((`action` =
|
||||
_utf8mb4'DOWNLOAD'),json_unquote(json_extract(`params`,_utf8mb4'$.id')),NULL)) VIRTUAL COMMENT '对于下载类型事件的文件ID',
|
||||
KEY `action` (`action`) COMMENT '操作类型索引',
|
||||
KEY `actor_index` (`actor`) COMMENT '操作者索引',
|
||||
KEY `time` (`time`) COMMENT '时间索引'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='统计信息';
|
||||
KEY `time` (`time`) COMMENT '时间索引',
|
||||
KEY `download_file_id_index` (`download_file_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='统计信息'
|
||||
</insert>
|
||||
<insert id="createUserTable">
|
||||
CREATE TABLE IF NOT EXISTS `user`
|
||||
@ -63,7 +64,8 @@
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
|
||||
`name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',
|
||||
`password` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户密码(MD5+SHA1)',
|
||||
`auth` enum ('admin','user') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'user' COMMENT '用户类型',
|
||||
`auth` enum ('admin','user') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'user' COMMENT
|
||||
'用户类型',
|
||||
`banned` tinyint(1) NOT NULL DEFAULT '0' COMMENT '用户是否被封禁',
|
||||
PRIMARY KEY (`id`) COMMENT 'ID索引',
|
||||
UNIQUE KEY `name_pk` (`name`),
|
||||
@ -74,4 +76,33 @@
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='用户表';
|
||||
</insert>
|
||||
<insert id="createRawFileView">
|
||||
CREATE OR REPLACE VIEW `raw_file` AS
|
||||
select `file`.`id` AS `id`,
|
||||
`file`.`name` AS `name`,
|
||||
`file`.`ext` AS `ext`,
|
||||
`file`.`size` AS `size`,
|
||||
`file`.`folder` AS `parent`,
|
||||
`file`.`uploader` AS `owner`,
|
||||
`user`.`name` AS `owner_name`,
|
||||
`file`.`upload_time` AS `time`,
|
||||
count(`statistics`.`time`) AS `down_count`,
|
||||
'FILE' AS `type`
|
||||
from ((`file` left join `user`
|
||||
on (((`user`.`id` = `file`.`uploader`) and (`user`.`banned` = 0)))) left join `statistics`
|
||||
on (((`statistics`.`action` = 'DOWNLOAD') and (`file`.`id` = `statistics`.`download_file_id`))))
|
||||
group by `file`.`id`
|
||||
union all
|
||||
select `folder`.`id` AS `id`,
|
||||
`folder`.`name` AS `name`,
|
||||
NULL AS `ext`,
|
||||
-(1) AS `size`,
|
||||
`folder`.`parent` AS `parent`,
|
||||
`folder`.`creator` AS `owner`,
|
||||
`user`.`name` AS `owner_name`,
|
||||
`folder`.`create_time` AS `time`,
|
||||
0 AS `down_count`,
|
||||
'FOLDER' AS `type`
|
||||
from (`folder` left join `user` on (((`user`.`id` = `folder`.`creator`) and (`user`.`banned` = 0))));
|
||||
</insert>
|
||||
</mapper>
|
@ -40,9 +40,13 @@ CREATE TABLE IF NOT EXISTS `statistics`
|
||||
`action` enum ('UPLOAD','DELETE','ACCESS','DOWNLOAD','SEARCH','LOGIN','INVITE','REGISTER') COLLATE utf8mb4_general_ci NOT NULL COMMENT '所做的操作',
|
||||
`params` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '操作的参数(在ACCESS操作中为空)',
|
||||
`time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作的时间',
|
||||
`download_file_id` int GENERATED ALWAYS AS (if((`action` = _utf8mb4'DOWNLOAD'),
|
||||
json_unquote(json_extract(`params`, _utf8mb4'$.id')),
|
||||
NULL)) VIRTUAL COMMENT '对于下载类型事件的文件ID',
|
||||
KEY `action` (`action`) COMMENT '操作类型索引',
|
||||
KEY `actor_index` (`actor`) COMMENT '操作者索引',
|
||||
KEY `time` (`time`) COMMENT '时间索引'
|
||||
KEY `time` (`time`) COMMENT '时间索引',
|
||||
KEY `download_file_id_index` (`download_file_id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='统计信息';
|
||||
@ -61,3 +65,30 @@ CREATE TABLE IF NOT EXISTS `user`
|
||||
AUTO_INCREMENT = 4
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='用户表';
|
||||
CREATE OR REPLACE VIEW `raw_file` AS
|
||||
select `file`.`id` AS `id`,
|
||||
`file`.`name` AS `name`,
|
||||
`file`.`ext` AS `ext`,
|
||||
`file`.`size` AS `size`,
|
||||
`file`.`folder` AS `parent`,
|
||||
`file`.`uploader` AS `owner`,
|
||||
`user`.`name` AS `owner_name`,
|
||||
`file`.`upload_time` AS `time`,
|
||||
count(`statistics`.`time`) AS `down_count`,
|
||||
'FILE' AS `type`
|
||||
from ((`file` left join `user`
|
||||
on (((`user`.`id` = `file`.`uploader`) and (`user`.`banned` = 0)))) left join `statistics`
|
||||
on (((`statistics`.`action` = 'DOWNLOAD') and (`file`.`id` = `statistics`.`download_file_id`))))
|
||||
group by `file`.`id`
|
||||
union all
|
||||
select `folder`.`id` AS `id`,
|
||||
`folder`.`name` AS `name`,
|
||||
NULL AS `ext`,
|
||||
-(1) AS `size`,
|
||||
`folder`.`parent` AS `parent`,
|
||||
`folder`.`creator` AS `owner`,
|
||||
`user`.`name` AS `owner_name`,
|
||||
`folder`.`create_time` AS `time`,
|
||||
0 AS `down_count`,
|
||||
'FOLDER' AS `type`
|
||||
from (`folder` left join `user` on (((`user`.`id` = `folder`.`creator`) and (`user`.`banned` = 0))));
|
||||
|
Loading…
x
Reference in New Issue
Block a user