This commit is contained in:
Qiu
2026-06-13 18:35:43 +08:00
commit 868598c2fd
185 changed files with 19611 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
+165
View File
@@ -0,0 +1,165 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.easypan</groupId>
<artifactId>easypan</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
<springboot.version>2.6.1</springboot.version>
<mybatis.version>1.3.2</mybatis.version>
<logback.version>1.2.10</logback.version>
<mysql.version>8.0.19</mysql.version>
<druid.version>1.2.16</druid.version>
<aspectjweaver.version>1.9.4</aspectjweaver.version>
<fastjson.version>1.2.66</fastjson.version>
<commons.lang3.version>3.4</commons.lang3.version>
<commons.codec.version>1.9</commons.codec.version>
<commons.io.version>2.5</commons.io.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--邮件发送-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${springboot.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- 数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 日志版本 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<!--切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--apache common-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons.codec.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.6.RELEASE</version>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.easypan.EasyPanApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,22 @@
package com.easypan;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement // 事务
@EnableScheduling // 定时任务
@EnableAsync // 异步调用
@MapperScan("com.easypan.mappers")
public class EasypanApplication {
public static void main(String[] args) {
SpringApplication.run(EasypanApplication.class, args);
}
}
@@ -0,0 +1,22 @@
package com.easypan.annotation;
import org.springframework.web.bind.annotation.Mapping;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface GlobalInterceptor {
// 校验参数
boolean checkParams() default false;
// 校验登陆
boolean checkLogin() default true;
// 校验管理员
boolean checkAdmin() default false;
}
@@ -0,0 +1,23 @@
package com.easypan.annotation;
import com.easypan.entity.enums.VerifyRegexEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
public @interface VerifyParam {
int min() default -1;
int max() default -1;
boolean required() default false;
//默认不校验
VerifyRegexEnum regex() default VerifyRegexEnum.NO;
}
@@ -0,0 +1,180 @@
package com.easypan.aspect;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.enums.ResponseCodeEnum;
import com.easypan.exception.BusinessException;
import com.easypan.service.UserInfoService;
import com.easypan.utils.StringTools;
import com.easypan.utils.VerifyUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
@Component
@Slf4j
@Aspect
public class GlobalOperationAspect {
private static final String TYPE_STRING = "java.lang.String";
private static final String TYPE_INTEGER = "java.lang.Integer";
private static final String TYPE_LONG = "java.lang.Long";
@Resource
private UserInfoService userInfoService;
@Resource
private AppConfig appConfig;
@Pointcut("@annotation(com.easypan.annotation.GlobalInterceptor)")
private void requestInterceptor() {
}
@Before("requestInterceptor()")
public void interceptorDo(JoinPoint point) throws BusinessException {
try {
Object target = point.getTarget();
Object[] arguments = point.getArgs();
String methodName = point.getSignature().getName();
Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
Method method = target.getClass().getMethod(methodName, parameterTypes);
GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);
if (null == interceptor) {
return;
}
/**
* 校验登陆
*/
if (interceptor.checkLogin() || interceptor.checkAdmin()) {
checkLogin(interceptor.checkAdmin());
}
/**
* 校验参数
*/
if (interceptor.checkParams()) {
validateParams(method, arguments);
}
} catch (BusinessException e) {
log.error("全局拦截器异常", e);
throw e;
} catch (Exception e) {
log.error("全局拦截器异常", e);
throw new BusinessException(ResponseCodeEnum.CODE_500);
} catch (Throwable e) {
log.error("全局拦截器异常", e);
throw new BusinessException(ResponseCodeEnum.CODE_500);
}
}
private void checkLogin(Boolean checkAdmin) {
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
SessionWebUserDto userDto = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);
if (userDto == null) {
throw new BusinessException(ResponseCodeEnum.CODE_901);
}
if (checkAdmin && ! userDto.getIsAdmin()) {
throw new BusinessException(ResponseCodeEnum.CODE_404);
}
}
private void validateParams(Method m, Object[] arguments) throws BusinessException {
Parameter[] parameters = m.getParameters();
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
Object value = arguments[i];
VerifyParam verifyParam = parameter.getAnnotation(VerifyParam.class);
if (verifyParam == null) {
continue;
}
//基本数据类型
if (TYPE_STRING.equals(parameter.getParameterizedType().getTypeName()) || TYPE_LONG.equals(parameter.getParameterizedType().getTypeName()) || TYPE_INTEGER.equals(parameter.getParameterizedType().getTypeName())) {
checkValue(value, verifyParam);
//如果传递的是对象
} else {
checkObjValue(parameter, value);
}
}
}
private void checkObjValue(Parameter parameter, Object value) {
try {
String typeName = parameter.getParameterizedType().getTypeName();
Class clazz = Class.forName(typeName);
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
VerifyParam fieldVerifyParam = field.getAnnotation(VerifyParam.class);
if (fieldVerifyParam == null) {
continue;
}
field.setAccessible(true);
Object resultValue = field.get(value);
checkValue(resultValue, fieldVerifyParam);
}
} catch (BusinessException e) {
log.error("校验参数失败", e);
throw e;
} catch (Exception e) {
log.error("校验参数失败", e);
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
}
/**
* 校验参数
*
* @param value
* @param verifyParam
* @throws BusinessException
*/
private void checkValue(Object value, VerifyParam verifyParam) throws BusinessException {
Boolean isEmpty = value == null || StringTools.isEmpty(value.toString());
Integer length = value == null ? 0 : value.toString().length();
/**
* 校验空
*/
if (isEmpty && verifyParam.required()) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
/**
* 校验长度
*/
if (!isEmpty && (verifyParam.max() != -1 && verifyParam.max() < length
|| verifyParam.min() != -1 && verifyParam.min() > length)) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
/**
* 校验正则
*/
if (!isEmpty && !StringTools.isEmpty(verifyParam.regex().getRegex())
&& !VerifyUtils.verify(verifyParam.regex(), String.valueOf(value))) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
}
}
@@ -0,0 +1,109 @@
package com.easypan.config;
import com.easypan.utils.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class AppConfig {
private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);
/**
* 文件目录
*/
@Value("${project.folder:}")
private String projectFolder;
/**
* 发送人
*/
@Value("${spring.mail.username:}")
private String sendUserName;
@Value("${admin.emails:}")
private String adminEmails;
public String getAdminEmails() {
return adminEmails;
}
@Value("${dev:false}")
private Boolean dev;
@Value("${qq.app.id:}")
private String qqAppId;
@Value("${qq.app.key:}")
private String qqAppKey;
@Value("${qq.url.authorization:}")
private String qqUrlAuthorization;
@Value("${qq.url.access.token:}")
private String qqUrlAccessToken;
@Value("${qq.url.openid:}")
private String qqUrlOpenId;
@Value("${qq.url.user.info:}")
private String qqUrlUserInfo;
@Value("${qq.url.redirect:}")
private String qqUrlRedirect;
public String getProjectFolder() {
if (!StringTools.isEmpty(projectFolder) && !projectFolder.endsWith("/")) {
projectFolder = projectFolder + "/";
}
return projectFolder;
}
public static Logger getLogger() {
return logger;
}
public String getSendUserName() {
return sendUserName;
}
public Boolean getDev() {
return dev;
}
public String getQqAppId() {
return qqAppId;
}
public String getQqAppKey() {
return qqAppKey;
}
public String getQqUrlAuthorization() {
return qqUrlAuthorization;
}
public String getQqUrlAccessToken() {
return qqUrlAccessToken;
}
public String getQqUrlOpenId() {
return qqUrlOpenId;
}
public String getQqUrlUserInfo() {
return qqUrlUserInfo;
}
public String getQqUrlRedirect() {
return qqUrlRedirect;
}
}
@@ -0,0 +1,27 @@
package com.easypan.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig<V> {
@Bean
public RedisTemplate<String, V> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, V> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置key的序列化方式
template.setKeySerializer(RedisSerializer.string());
// 设置value的序列化方式
template.setValueSerializer(RedisSerializer.json());
// 设置hash的key的序列化方式
template.setHashKeySerializer(RedisSerializer.string());
// 设置hash的value的序列化方式
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
}
@@ -0,0 +1,55 @@
package com.easypan.controller;
import com.easypan.controller.basecontroller.BaseController;
import com.easypan.entity.enums.ResponseCodeEnum;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
@RestControllerAdvice
public class AGlobalExceptionHandlerController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(AGlobalExceptionHandlerController.class);
@ExceptionHandler(value = Exception.class)
Object handleException(Exception e, HttpServletRequest request) {
logger.error("请求错误,请求地址{},错误信息:", request.getRequestURL(), e);
ResponseVO ajaxResponse = new ResponseVO();
//404
if (e instanceof NoHandlerFoundException) {
ajaxResponse.setCode(ResponseCodeEnum.CODE_404.getCode());
ajaxResponse.setInfo(ResponseCodeEnum.CODE_404.getMsg());
ajaxResponse.setStatus(STATUC_ERROR);
} else if (e instanceof BusinessException) {
//业务错误
BusinessException biz = (BusinessException) e;
ajaxResponse.setCode(biz.getCode() == null ? ResponseCodeEnum.CODE_600.getCode() : biz.getCode());
ajaxResponse.setInfo(biz.getMessage());
ajaxResponse.setStatus(STATUC_ERROR);
} else if (e instanceof BindException|| e instanceof MethodArgumentTypeMismatchException) {
//参数类型错误
ajaxResponse.setCode(ResponseCodeEnum.CODE_600.getCode());
ajaxResponse.setInfo(ResponseCodeEnum.CODE_600.getMsg());
ajaxResponse.setStatus(STATUC_ERROR);
} else if (e instanceof DuplicateKeyException) {
//主键冲突
ajaxResponse.setCode(ResponseCodeEnum.CODE_601.getCode());
ajaxResponse.setInfo(ResponseCodeEnum.CODE_601.getMsg());
ajaxResponse.setStatus(STATUC_ERROR);
} else {
ajaxResponse.setCode(ResponseCodeEnum.CODE_500.getCode());
ajaxResponse.setInfo(ResponseCodeEnum.CODE_500.getMsg());
ajaxResponse.setStatus(STATUC_ERROR);
}
return ajaxResponse;
}
}
@@ -0,0 +1,283 @@
package com.easypan.controller;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.utils.RedisComponent;
import com.easypan.controller.basecontroller.BaseController;
import com.easypan.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.CreateImageCode;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.enums.VerifyRegexEnum;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.exception.BusinessException;
import com.easypan.service.EmailCodeService;
import com.easypan.service.UserInfoService;
import com.easypan.utils.StringTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@Slf4j
@RestController
public class AccountController extends BaseController {
@Resource
private AppConfig appConfig;
@Resource
private UserInfoService userInfoService;
@Resource
private EmailCodeService emailCodeService;
@Resource
private RedisComponent redisComponent;
private static final String CONTENT_TYPE = "Content-Type";
private static final String CONTENT_TYPE_VALUE = "application/json;charset=UTF-8";
/**
* 根据请求类型返回验证码并存入session
*
* @param type 0:登录注册 1:邮箱验证码发送 默认0
*/
@GetMapping("/checkCode")
public void checkCode(HttpServletResponse response, HttpSession session
, @RequestParam(value = "type", required = false) Integer type) throws IOException {
CreateImageCode vCode = new CreateImageCode(130, 38, 5, 10);
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache"); //响应消息不能缓存
response.setDateHeader("Expires", 0);
response.setContentType("image/jpeg");
String code = vCode.getCode();
if (type == null || type == 0) {
session.setAttribute(Constants.CHECK_CODE_KEY, code);
} else {
session.setAttribute(Constants.CHECK_CODE_KEY_EMAIL, code);
}
vCode.write(response.getOutputStream());
}
/**
* @param email 需要接收验证码的邮箱
* @param checkCode 发送给服务器的验证码
* @param type 0:注册 1:找回密码
*/
@PostMapping("/sendEmailCode")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO sendEmailCode(HttpSession session,
@VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
@VerifyParam(required = true) String checkCode,
@VerifyParam(required = true) Integer type) {
try {
// 如果验证码错误
if (!checkCode.equals(session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) {
throw new BusinessException("验证码错误");
}
// 如果验证码正确,发送邮箱验证码
emailCodeService.sendEmailCode(email, type);
return getSuccessResponseVO(null);
} finally {
// 删除session中保存的邮箱验证码
session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL);
}
}
@PostMapping("/register")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO register(HttpSession session,
@VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
@VerifyParam(required = true, max = 20) String nickName,
@VerifyParam(required = true, regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18) String password,
@VerifyParam(required = true) String checkCode,
@VerifyParam(required = true) String emailCode) {
try {
if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
throw new BusinessException("图片验证码不正确");
}
userInfoService.register(email, nickName, password, emailCode);
return getSuccessResponseVO(null);
} finally {
session.removeAttribute(Constants.CHECK_CODE_KEY);
}
}
@PostMapping("/login")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO login(HttpSession session,
@VerifyParam(required = true) String email,
@VerifyParam(required = true) String password,
@VerifyParam(required = true) String checkCode) {
try {
if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
throw new BusinessException("图片验证码不正确");
}
SessionWebUserDto sessionWebUserDto = userInfoService.login(email, password);
session.setAttribute(Constants.SESSION_KEY, sessionWebUserDto);
return getSuccessResponseVO(sessionWebUserDto);
} finally {
session.removeAttribute(Constants.CHECK_CODE_KEY);
}
}
@RequestMapping("/resetPwd")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO resetPwd(HttpSession session,
@VerifyParam(required = true, regex = VerifyRegexEnum.EMAIL, max = 150) String email,
@VerifyParam(required = true, regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18) String password,
@VerifyParam(required = true) String checkCode,
@VerifyParam(required = true) String emailCode) {
try {
if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY))) {
throw new BusinessException("图片验证码不正确");
}
userInfoService.resetPwd(email, password, emailCode);
return getSuccessResponseVO(null);
} finally {
session.removeAttribute(Constants.CHECK_CODE_KEY);
}
}
@GetMapping("/updatePWD/{pwd}")
public ResponseVO resetPwd1(@PathVariable String pwd) {
userInfoService.resetPwd("test@qq.com", pwd, "123");
return getSuccessResponseVO(null);
}
// 获取用户头像
@GetMapping("/getAvatar/{userId}")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public void getAvatar(HttpServletResponse response,
@VerifyParam(required = true) @PathVariable("userId") String userId) {
// 得到头像根目录 = /file + /avatar
String avatarFolderName = Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_AVATAR_NAME;
// 从AppConfig中得到项目根目录,从而得到放置头像文件夹的绝对路径
File folder = new File(appConfig.getProjectFolder() + avatarFolderName);
if (!folder.exists()) {
// 不存在就创建
folder.mkdirs();
}
// 根据userId得到用户头像的绝对路径 = 放置头像文件夹的绝对路径 + userId + .jpg(统一后缀)
String avatarPath = appConfig.getProjectFolder() + avatarFolderName + "/" + userId + Constants.AVATAR_SUFFIX;
File file = new File(avatarPath);
// 如果找不到该用户的头像
if (!file.exists()) {
// 默认头
avatarPath = appConfig.getProjectFolder() + avatarFolderName + "/" + Constants.AVATAR_DEFUALT;
// 获取系统默认头像
if (!new File(avatarPath).exists()) {
// 获取默认头像失败
printNoDefaultImage(response);
return;
}
}
// 输出
response.setContentType("image/jpg");
readFile(response, avatarPath);
}
// 解决输出默认头像失败问题
private void printNoDefaultImage(HttpServletResponse response) {
response.setHeader(CONTENT_TYPE, CONTENT_TYPE_VALUE);
response.setStatus(HttpStatus.OK.value());
PrintWriter writer = null;
try {
writer = response.getWriter();
writer.print("请在头像目录下放置默认头像default_avatar.jpg");
writer.close();
} catch (Exception e) {
log.error("输出无默认图失败", e);
} finally {
writer.close();
}
}
@GetMapping("/getUserInfo")
@GlobalInterceptor
public ResponseVO getUserInfo(HttpSession session) {
SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
return getSuccessResponseVO(sessionWebUserDto);
}
@PostMapping("/getUseSpace")
@GlobalInterceptor
public ResponseVO getUseSpace(HttpSession session) {
SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
return getSuccessResponseVO(redisComponent.getUserSpaceUse(sessionWebUserDto.getUserId()));
}
@PostMapping("/logout")
public ResponseVO logout(HttpSession session) {
session.invalidate();
return getSuccessResponseVO(null);
}
@PostMapping("/updateUserAvatar")
@GlobalInterceptor
public ResponseVO updateUserAvatar(HttpSession session, MultipartFile avatar) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
// 得到头像文件夹
String baseFolder = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE;
File targetFileFolder = new File(baseFolder + Constants.FILE_FOLDER_AVATAR_NAME);
// 如果不存在就创建
if (!targetFileFolder.exists()) {
targetFileFolder.mkdirs();
}
// 得到新头像绝对路径
File targetFile = new File(targetFileFolder.getPath() + "/" + webUserDto.getUserId() + Constants.AVATAR_SUFFIX);
try {
// 输出
avatar.transferTo(targetFile);
} catch (Exception e) {
log.error("上传头像失败", e);
}
// 同时将数据库中qq头像设为空
UserInfo userInfo = new UserInfo();
userInfo.setQqAvatar("");
userInfoService.updateUserInfoByUserId(userInfo, webUserDto.getUserId());
webUserDto.setAvatar(null);
//更新session
session.setAttribute(Constants.SESSION_KEY, webUserDto);
return getSuccessResponseVO(null);
}
@PostMapping("/updatePassword")
@GlobalInterceptor(checkParams = true)
public ResponseVO updatePassword(HttpSession session,
@VerifyParam(required = true, regex = VerifyRegexEnum.PASSWORD, min = 8, max = 18) String password) {
SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
UserInfo userInfo = new UserInfo();
userInfo.setPassword(StringTools.encodeByMD5(password));
userInfoService.updateUserInfoByUserId(userInfo, sessionWebUserDto.getUserId());
return getSuccessResponseVO(null);
}
}
@@ -0,0 +1,154 @@
package com.easypan.controller;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.utils.RedisComponent;
import com.easypan.controller.commonfilecontroller.CommonFileController;
import com.easypan.entity.dto.SysSettingsDto;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.query.UserInfoQuery;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.entity.vo.UserInfoVO;
import com.easypan.service.FileInfoService;
import com.easypan.service.UserInfoService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/admin")
public class AdminController extends CommonFileController {
@Resource
private RedisComponent redisComponent;
@Resource
private UserInfoService userInfoService;
@Resource
private FileInfoService fileInfoService;
@RequestMapping("/getSysSettings")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO getSysSettings() {
return getSuccessResponseVO(redisComponent.getSysSettingsDto());
}
@RequestMapping("/saveSysSettings")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO saveSysSettings(
@VerifyParam(required = true) String registerEmailTitle,
@VerifyParam(required = true) String registerEmailContent,
@VerifyParam(required = true) Integer userInitUseSpace) {
SysSettingsDto sysSettingsDto = new SysSettingsDto();
sysSettingsDto.setRegisterEmailTitle(registerEmailTitle);
sysSettingsDto.setRegisterEmailContent(registerEmailContent);
sysSettingsDto.setUserInitUseSpace(userInitUseSpace);
redisComponent.saveSysSettingsDto(sysSettingsDto);
return getSuccessResponseVO(null);
}
@RequestMapping("/loadUserList")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO loadUser(UserInfoQuery userInfoQuery) {
userInfoQuery.setOrderBy("join_time desc");
PaginationResultVO resultVO = userInfoService.findListByPage(userInfoQuery);
return getSuccessResponseVO(convert2PaginationVO(resultVO, UserInfoVO.class));
}
@RequestMapping("/updateUserStatus")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO updateUserStatus(@VerifyParam(required = true) String userId,
@VerifyParam(required = true) Integer status) {
userInfoService.updateUserStatus(userId, status);
return getSuccessResponseVO(null);
}
@RequestMapping("/updateUserSpace")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO updateUserSpace(@VerifyParam(required = true) String userId, @VerifyParam(required = true) Integer changeSpace) {
userInfoService.changeUserSpace(userId, changeSpace);
return getSuccessResponseVO(null);
}
/**
* 查询所有文件
*
* @param query
* @return
*/
@RequestMapping("/loadFileList")
@GlobalInterceptor(checkParams = true)
public ResponseVO loadDataList(FileInfoQuery query) {
query.setOrderBy("last_update_time desc");
query.setQueryNickName(true);
PaginationResultVO resultVO = fileInfoService.findListByPage(query);
return getSuccessResponseVO(resultVO);
}
@RequestMapping("/getFolderInfo")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO getFolderInfo(@VerifyParam(required = true) String path) {
return super.getFolderInfo(path, null);
}
@RequestMapping("/getFile/{userId}/{fileId}")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public void getFile(HttpServletResponse response,
@PathVariable("userId") @VerifyParam(required = true) String userId,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
super.getFile(response, fileId, userId);
}
@RequestMapping("/ts/getVideoInfo/{userId}/{fileId}")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public void getVideoInfo(HttpServletResponse response,
@PathVariable("userId") @VerifyParam(required = true) String userId,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
super.getFile(response, fileId, userId);
}
@RequestMapping("/createDownloadUrl/{userId}/{fileId}")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO createDownloadUrl(@PathVariable("userId") @VerifyParam(required = true) String userId,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
return super.createDownloadUrl(fileId, userId);
}
/**
* 下载
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/download/{code}")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public void download(HttpServletRequest request, HttpServletResponse response,
@PathVariable("code") @VerifyParam(required = true) String code) throws Exception {
super.download(request, response, code);
}
@RequestMapping("/delFile")
@GlobalInterceptor(checkParams = true, checkAdmin = true)
public ResponseVO delFile(@VerifyParam(required = true) String fileIdAndUserIds) {
String[] fileIdAndUserIdArray = fileIdAndUserIds.split(",");
for (String fileIdAndUserId : fileIdAndUserIdArray) {
String[] itemArray = fileIdAndUserId.split("_");
fileInfoService.delFileBatch(itemArray[0], itemArray[1], true);
}
return getSuccessResponseVO(null);
}
}
@@ -0,0 +1,195 @@
package com.easypan.controller;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.controller.basecontroller.BaseController;
import com.easypan.controller.commonfilecontroller.CommonFileController;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.dto.UploadResultDto;
import com.easypan.entity.enums.FileCategoryEnums;
import com.easypan.entity.enums.FileDelFlagEnums;
import com.easypan.entity.enums.FileFolderTypeEnums;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.vo.FileInfoVO;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.service.FileInfoService;
import com.easypan.utils.CopyTools;
import com.easypan.utils.StringTools;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
/**
* 文件信息 Controller
*/
@RestController
@RequestMapping("/file")
public class FileInfoController extends CommonFileController {
@Resource
private FileInfoService fileInfoService;
@PostMapping("/loadDataList")
@GlobalInterceptor
public ResponseVO loadDataList(HttpSession session, FileInfoQuery query, String category) {
FileCategoryEnums categoryEnum = FileCategoryEnums.getByCode(category);
if (categoryEnum != null) {
query.setFileCategory(categoryEnum.getCategory());
}
query.setUserId(getUserInfoFromSession(session).getUserId());
// 排序规则:先展示文件夹,然后按照修改时间排序
query.setOrderBy(Constants.ORDER_RULE);
query.setDelFlag(FileDelFlagEnums.USING.getFlag());
// 调用service方法得到分页对象,其中List<FileInfo>
PaginationResultVO result = fileInfoService.findListByPage(query);
// 集合元素映射为FileInfoVO再返回
return getSuccessResponseVO(convert2PaginationVO(result, FileInfoVO.class));
}
/**
* @param fileId 非必传,第一个分片文件不传
* @param file 传的文件
* @param fileName 文件名
* @param filePid 在哪一个目录
* @param fileMd5 前端做的
* @param chunkIndex 第几个分片
* @param chunks 总共有多少个分片
* @return
*/
@PostMapping("/uploadFile")
@GlobalInterceptor(checkParams = true)
public ResponseVO uploadFile(HttpSession session,
String fileId,
MultipartFile file,
@VerifyParam(required = true) String fileName,
@VerifyParam(required = true) String filePid,
@VerifyParam(required = true) String fileMd5,
@VerifyParam(required = true) Integer chunkIndex,
@VerifyParam(required = true) Integer chunks) {
// 从session中获取SessionWebUserDto对象
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
UploadResultDto resultDto = fileInfoService.uploadFile(webUserDto, fileId, file, fileName,
filePid, fileMd5, chunkIndex, chunks);
return getSuccessResponseVO(resultDto);
}
// 得到缩略图
@GetMapping("/getImage/{imageFolder}/{imageName}")
public void getImage(HttpServletResponse response,
@PathVariable("imageFolder") String imageFolder,
@PathVariable("imageName") String imageName) {
super.getImage(response, imageFolder, imageName);
}
@GetMapping("/ts/getVideoInfo/{fileId}")
public void getVideoInfo(HttpServletResponse response,
HttpSession session,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
super.getFile(response, fileId, webUserDto.getUserId());
}
@RequestMapping("/getFile/{fileId}")
public void getFile(HttpServletResponse response,
HttpSession session,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
super.getFile(response, fileId, webUserDto.getUserId());
}
@PostMapping("/newFoloder")
@GlobalInterceptor(checkParams = true)
public ResponseVO newFolder(HttpSession session,
@VerifyParam(required = true) String filePid,
@VerifyParam(required = true) String fileName) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
FileInfo fileInfo = fileInfoService.newFolder(filePid, webUserDto.getUserId(), fileName);
return getSuccessResponseVO(fileInfo);
}
/**
* @param path 目录1/目录2/目录3...
*/
@PostMapping("/getFolderInfo")
@GlobalInterceptor(checkParams = true)
public ResponseVO getFolderInfo(HttpSession session,
@VerifyParam(required = true) String path) {
return super.getFolderInfo(path, getUserInfoFromSession(session).getUserId());
}
@PostMapping("/rename")
@GlobalInterceptor(checkParams = true)
public ResponseVO rename(HttpSession session,
@VerifyParam(required = true) String fileId,
@VerifyParam(required = true) String fileName) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
FileInfo fileInfo = fileInfoService.rename(fileId, webUserDto.getUserId(), fileName);
return getSuccessResponseVO(CopyTools.copy(fileInfo, FileInfoVO.class));
}
// 加载除自己外的文件夹
@PostMapping("/loadAllFolder")
@GlobalInterceptor(checkParams = true)
public ResponseVO loadAllFolder(HttpSession session,
@VerifyParam(required = true) String filePid,
String currentFileIds) {
List<FileInfo> fileInfoList = fileInfoService.loadAllFolder(
getUserInfoFromSession(session).getUserId(), filePid, currentFileIds);
return getSuccessResponseVO(CopyTools.copyList(fileInfoList, FileInfoVO.class));
}
@PostMapping("/changeFileFolder")
@GlobalInterceptor(checkParams = true)
public ResponseVO changeFileFolder(HttpSession session,
@VerifyParam(required = true) String fileIds,
@VerifyParam(required = true) String filePid) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
fileInfoService.changeFileFolder(fileIds, filePid, webUserDto.getUserId());
return getSuccessResponseVO(null);
}
@PostMapping("/createDownloadUrl/{fileId}")
@GlobalInterceptor(checkParams = true)
public ResponseVO createDownloadUrl(HttpSession session,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
return super.createDownloadUrl(fileId, getUserInfoFromSession(session).getUserId());
}
// 无需登陆校验
@GetMapping("/download/{code}")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public void download(HttpServletRequest request,
HttpServletResponse response,
@PathVariable("code") @VerifyParam(required = true) String code) throws Exception {
super.download(request, response, code);
}
@PostMapping("/delFile")
@GlobalInterceptor(checkParams = true)
public ResponseVO delFile(HttpSession session,
@VerifyParam(required = true) String fileIds) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
fileInfoService.removeFile2RecycleBatch(webUserDto.getUserId(), fileIds);
return getSuccessResponseVO(null);
}
}
@@ -0,0 +1,61 @@
package com.easypan.controller;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.controller.basecontroller.BaseController;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.enums.FileDelFlagEnums;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.vo.FileInfoVO;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.service.FileInfoService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/recycle")
public class RecycleController extends BaseController {
@Resource
private FileInfoService fileInfoService;
// 加载回收站列表
@PostMapping("/loadRecycleList")
@GlobalInterceptor(checkParams = true)
public ResponseVO loadRecycleList(HttpSession session, Integer pageNo, Integer pageSize) {
FileInfoQuery query = new FileInfoQuery();
query.setPageSize(pageSize);
query.setPageNo(pageNo);
query.setUserId(getUserInfoFromSession(session).getUserId());
query.setOrderBy("recovery_time desc");
query.setDelFlag(FileDelFlagEnums.RECYCLE.getFlag());
PaginationResultVO result = fileInfoService.findListByPage(query);
return getSuccessResponseVO(convert2PaginationVO(result, FileInfoVO.class));
}
// 回收站文件还原到根目录
@RequestMapping("/recoverFile")
@GlobalInterceptor(checkParams = true)
public ResponseVO recoverFile(HttpSession session,
@VerifyParam(required = true) String fileIds) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
fileInfoService.recoverFileBatch(webUserDto.getUserId(), fileIds);
return getSuccessResponseVO(null);
}
@PostMapping("/delFile")
@GlobalInterceptor(checkParams = true)
public ResponseVO delFile(HttpSession session,
@VerifyParam(required = true) String fileIds) {
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
fileInfoService.delFileBatch(webUserDto.getUserId(), fileIds, false);
return getSuccessResponseVO(null);
}
}
@@ -0,0 +1,62 @@
package com.easypan.controller;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.controller.basecontroller.BaseController;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.po.FileShare;
import com.easypan.entity.query.FileShareQuery;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.service.FileShareService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
@RestController("shareController")
@RequestMapping("/share")
public class ShareController extends BaseController {
@Resource
private FileShareService fileShareService;
@PostMapping("/loadShareList")
@GlobalInterceptor(checkParams = true)
public ResponseVO loadShareList(HttpSession session, FileShareQuery query) {
query.setOrderBy("share_time desc");
SessionWebUserDto userDto = getUserInfoFromSession(session);
query.setUserId(userDto.getUserId());
query.setQueryFileName(true);
PaginationResultVO resultVO = this.fileShareService.findListByPage(query);
return getSuccessResponseVO(resultVO);
}
@PostMapping("/shareFile")
@GlobalInterceptor(checkParams = true)
public ResponseVO shareFile(HttpSession session,
@VerifyParam(required = true) String fileId,
@VerifyParam(required = true) Integer validType,
String code) {
SessionWebUserDto userDto = getUserInfoFromSession(session);
FileShare share = new FileShare();
share.setFileId(fileId);
share.setValidType(validType);
share.setCode(code);
share.setUserId(userDto.getUserId());
fileShareService.saveShare(share);
return getSuccessResponseVO(share);
}
@PostMapping("/cancelShare")
@GlobalInterceptor(checkParams = true)
public ResponseVO cancelShare(HttpSession session,
@VerifyParam(required = true) String shareIds) {
SessionWebUserDto userDto = getUserInfoFromSession(session);
fileShareService.deleteFileShareBatch(shareIds.split(","), userDto.getUserId());
return getSuccessResponseVO(null);
}
}
@@ -0,0 +1,205 @@
package com.easypan.controller;
import com.easypan.annotation.GlobalInterceptor;
import com.easypan.annotation.VerifyParam;
import com.easypan.controller.commonfilecontroller.CommonFileController;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionShareDto;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.enums.FileDelFlagEnums;
import com.easypan.entity.enums.ResponseCodeEnum;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.po.FileShare;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.vo.FileInfoVO;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.entity.vo.ShareInfoVO;
import com.easypan.exception.BusinessException;
import com.easypan.service.FileShareService;
import com.easypan.service.UserInfoService;
import com.easypan.utils.CopyTools;
import com.easypan.utils.StringTools;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
@RestController
@RequestMapping("/showShare")
public class WebShareController extends CommonFileController {
@Resource
private FileShareService fileShareService;
@Resource
private UserInfoService userInfoService;
//
@PostMapping("/getShareLoginInfo")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO getShareLoginInfo(HttpSession session,
@VerifyParam(required = true) String shareId) {
SessionShareDto shareSessionDto = getSessionShareFromSession(session, shareId);
if (shareSessionDto == null) {
return getSuccessResponseVO(null);
}
ShareInfoVO shareInfoVO = getShareInfoCommon(shareId);
//判断是否是当前用户分享的文件
SessionWebUserDto userDto = getUserInfoFromSession(session);
shareInfoVO.setCurrentUser(userDto != null &&
userDto.getUserId().equals(shareSessionDto.getShareUserId()));
return getSuccessResponseVO(shareInfoVO);
}
/**
* 获取分享信息
*/
@PostMapping("/getShareInfo")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO getShareInfo(@VerifyParam(required = true) String shareId) {
return getSuccessResponseVO(getShareInfoCommon(shareId));
}
private ShareInfoVO getShareInfoCommon(String shareId) {
// 根据shareId获得FileShare
FileShare share = fileShareService.getFileShareByShareId(shareId);
// 如果FileShare为空或者已经过期
if (share == null || (share.getExpireTime() != null && new Date().after(share.getExpireTime()))) {
throw new BusinessException(ResponseCodeEnum.CODE_902.getMsg());
}
// FileShare映射为ShareInfoVO
ShareInfoVO shareInfoVO = CopyTools.copy(share, ShareInfoVO.class);
FileInfo fileInfo = fileInfoService.getFileInfoByFileIdAndUserId(share.getFileId(), share.getUserId());
if (fileInfo == null || !FileDelFlagEnums.USING.getFlag().equals(fileInfo.getDelFlag())) {
throw new BusinessException(ResponseCodeEnum.CODE_902.getMsg());
}
shareInfoVO.setFileName(fileInfo.getFileName());
UserInfo userInfo = userInfoService.getUserInfoByUserId(share.getUserId());
shareInfoVO.setNickName(userInfo.getNickName());
shareInfoVO.setAvatar(userInfo.getQqAvatar());
shareInfoVO.setUserId(userInfo.getUserId());
return shareInfoVO;
}
/**
* 校验分享码
*/
@RequestMapping("/checkShareCode")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO checkShareCode(HttpSession session,
@VerifyParam(required = true) String shareId,
@VerifyParam(required = true) String code) {
SessionShareDto shareSessionDto = fileShareService.checkShareCode(shareId, code);
session.setAttribute(Constants.SESSION_SHARE_KEY + shareId, shareSessionDto);
return getSuccessResponseVO(null);
}
// 只能分享一个文件或者文件夹(可包含多个子文件夹和子文件)
@RequestMapping("/loadFileList")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO loadFileList(HttpSession session,
@VerifyParam(required = true) String shareId, String filePid) {
// 查询出对应链接下的SessionShareDto
SessionShareDto shareSessionDto = checkShare(session, shareId);
FileInfoQuery query = new FileInfoQuery();
// 如果父目录不是根目录
if (!StringTools.isEmpty(filePid) && !Constants.ZERO_STR.equals(filePid)) {
// fileInfoService.checkRootFilePid(shareSessionDto.getFileId(), shareSessionDto.getShareUserId(), filePid);
query.setFilePid(filePid);
} else {
// 如果是根目录
query.setFileId(shareSessionDto.getFileId());
}
query.setUserId(shareSessionDto.getShareUserId());
query.setOrderBy("last_update_time desc");
query.setDelFlag(FileDelFlagEnums.USING.getFlag());
PaginationResultVO resultVO = fileInfoService.findListByPage(query);
return getSuccessResponseVO(convert2PaginationVO(resultVO, FileInfoVO.class));
}
// 判断分享是否失效
private SessionShareDto checkShare(HttpSession session, String shareId) {
SessionShareDto shareSessionDto = getSessionShareFromSession(session, shareId);
if (shareSessionDto == null) {
throw new BusinessException(ResponseCodeEnum.CODE_903);
}
if (shareSessionDto.getExpireTime() != null && new Date().after(shareSessionDto.getExpireTime())) {
throw new BusinessException(ResponseCodeEnum.CODE_902);
}
return shareSessionDto;
}
@PostMapping("/getFolderInfo")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO getFolderInfo(HttpSession session,
@VerifyParam(required = true) String shareId,
@VerifyParam(required = true) String path) {
SessionShareDto shareSessionDto = checkShare(session, shareId);
return super.getFolderInfo(path, shareSessionDto.getShareUserId());
}
@RequestMapping("/getFile/{shareId}/{fileId}")
public void getFile(HttpServletResponse response, HttpSession session,
@PathVariable("shareId") @VerifyParam(required = true) String shareId,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
SessionShareDto shareSessionDto = checkShare(session, shareId);
super.getFile(response, fileId, shareSessionDto.getShareUserId());
}
@RequestMapping("/ts/getVideoInfo/{shareId}/{fileId}")
public void getVideoInfo(HttpServletResponse response,
HttpSession session,
@PathVariable("shareId") @VerifyParam(required = true) String shareId,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
SessionShareDto shareSessionDto = checkShare(session, shareId);
super.getFile(response, fileId, shareSessionDto.getShareUserId());
}
@RequestMapping("/createDownloadUrl/{shareId}/{fileId}")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public ResponseVO createDownloadUrl(HttpSession session,
@PathVariable("shareId") @VerifyParam(required = true) String shareId,
@PathVariable("fileId") @VerifyParam(required = true) String fileId) {
SessionShareDto shareSessionDto = checkShare(session, shareId);
return super.createDownloadUrl(fileId, shareSessionDto.getShareUserId());
}
@RequestMapping("/download/{code}")
@GlobalInterceptor(checkLogin = false, checkParams = true)
public void download(HttpServletRequest request, HttpServletResponse response,
@PathVariable("code") @VerifyParam(required = true) String code) throws Exception {
super.download(request, response, code);
}
@RequestMapping("/saveShare")
@GlobalInterceptor(checkParams = true)
public ResponseVO saveShare(HttpSession session,
@VerifyParam(required = true) String shareId,
@VerifyParam(required = true) String shareFileIds,
@VerifyParam(required = true) String myFolderId) {
// 校验分享链接
SessionShareDto shareSessionDto = checkShare(session, shareId);
// 校验登陆用户和分享用户
SessionWebUserDto webUserDto = getUserInfoFromSession(session);
if (shareSessionDto.getShareUserId().equals(webUserDto.getUserId())) {
throw new BusinessException("自己分享的文件无法保存到自己的网盘");
}
fileInfoService.saveShare(shareSessionDto.getFileId(), shareFileIds, myFolderId,
shareSessionDto.getShareUserId(), webUserDto.getUserId());
return getSuccessResponseVO(null);
}
}
@@ -0,0 +1,100 @@
package com.easypan.controller.basecontroller;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionShareDto;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.enums.ResponseCodeEnum;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.utils.CopyTools;
import com.easypan.utils.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
public class BaseController {
private static final Logger logger = LoggerFactory.getLogger(BaseController.class);
protected static final String STATUC_SUCCESS = "success";
protected static final String STATUC_ERROR = "error";
protected <T> ResponseVO getSuccessResponseVO(T t) {
ResponseVO<T> responseVO = new ResponseVO<>();
responseVO.setStatus(STATUC_SUCCESS);
responseVO.setCode(ResponseCodeEnum.CODE_200.getCode());
responseVO.setInfo(ResponseCodeEnum.CODE_200.getMsg());
responseVO.setData(t);
return responseVO;
}
// 从session中获得SessionWebUserDto对象
protected SessionWebUserDto getUserInfoFromSession(HttpSession session) {
SessionWebUserDto sessionWebUserDto = (SessionWebUserDto) session.getAttribute(Constants.SESSION_KEY);
return sessionWebUserDto;
}
protected SessionShareDto getSessionShareFromSession(HttpSession session, String shareId) {
SessionShareDto sessionShareDto = (SessionShareDto)
session.getAttribute(Constants.SESSION_SHARE_KEY + shareId);
return sessionShareDto;
}
// 输出文件
protected void readFile(HttpServletResponse response, String filePath) {
if (!StringTools.pathIsOk(filePath)) {
return;
}
OutputStream out = null;
FileInputStream in = null;
try {
File file = new File(filePath);
if (!file.exists()) {
return;
}
in = new FileInputStream(file);
byte[] byteData = new byte[1024];
out = response.getOutputStream();
int len = 0;
while ((len = in.read(byteData)) != -1) {
out.write(byteData, 0, len);
}
out.flush();
} catch (Exception e) {
logger.error("读取文件异常", e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
logger.error("IO异常", e);
}
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
logger.error("IO异常", e);
}
}
}
}
protected <S, T> PaginationResultVO<T> convert2PaginationVO(PaginationResultVO<S> result, Class<T> clazz) {
PaginationResultVO<T> resultVO = new PaginationResultVO<>();
resultVO.setList(CopyTools.copyList(result.getList(), clazz));
resultVO.setPageNo(result.getPageNo());
resultVO.setPageSize(result.getPageSize());
resultVO.setPageTotal(result.getPageTotal());
resultVO.setTotalCount(result.getTotalCount());
return resultVO;
}
}
@@ -0,0 +1,157 @@
package com.easypan.controller.commonfilecontroller;
import com.easypan.utils.RedisComponent;
import com.easypan.controller.basecontroller.BaseController;
import com.easypan.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.DownloadFileDto;
import com.easypan.entity.enums.FileCategoryEnums;
import com.easypan.entity.enums.FileFolderTypeEnums;
import com.easypan.entity.enums.ResponseCodeEnum;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.vo.FolderVO;
import com.easypan.entity.vo.ResponseVO;
import com.easypan.exception.BusinessException;
import com.easypan.service.FileInfoService;
import com.easypan.utils.CopyTools;
import com.easypan.utils.StringTools;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URLEncoder;
import java.util.List;
public class CommonFileController extends BaseController {
@Resource
protected FileInfoService fileInfoService;
@Resource
protected AppConfig appConfig;
@Resource
private RedisComponent redisComponent;
// 获取缩略图
public void getImage(HttpServletResponse response, String imageFolder, String imageName) {
if (StringTools.isEmpty(imageFolder) || StringUtils.isBlank(imageName)) {
return;
}
String imageSuffix = StringTools.getFileSuffix(imageName);
String filePath = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE
+ "/" + imageFolder + "/" + imageName;
imageSuffix = imageSuffix.replace(".", "");
String contentType = "image/" + imageSuffix;
response.setContentType(contentType);
response.setHeader("Cache-Control", "max-age=2592000");
readFile(response, filePath);
}
// 处理第一次获取.m3u8索引文件和后续获取.ts分片文件
// 同时也处理其他文件
protected void getFile(HttpServletResponse response, String fileId, String userId) {
String filePath = null;
if (fileId.endsWith(".ts")) {
// 如果是后去ts分片文件
String[] tsAarray = fileId.split("_");
String realFileId = tsAarray[0];
FileInfo fileInfo = fileInfoService.getFileInfoByFileIdAndUserId(realFileId, userId);
if (fileInfo == null) {
return;
}
String fileName = fileInfo.getFilePath();
fileName = StringTools.getFileNameNoSuffix(fileName) + "/" + fileId;
filePath = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + "/" + fileName;
} else {
// 第一次获取.m3u8索引文件
FileInfo fileInfo = fileInfoService.getFileInfoByFileIdAndUserId(fileId, userId);
if (fileInfo == null) {
return;
}
//视频文件读取.m3u8文件
if (FileCategoryEnums.VIDEO.getCategory().equals(fileInfo.getFileCategory())) {
//重新设置文件路径
String fileNameNoSuffix = StringTools.getFileNameNoSuffix(fileInfo.getFilePath());
filePath = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE
+ "/" + fileNameNoSuffix + "/" + Constants.M3U8_NAME;
} else {
// 处理其他文件
filePath = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE
+ "/" + fileInfo.getFilePath();
}
}
File file = new File(filePath);
if (!file.exists()) {
return;
}
readFile(response, filePath);
}
// 根据前端传来的path{fileId1/fileId2/fileId3/...}进行查询排序
protected ResponseVO getFolderInfo(String path, String userId) {
String[] pathArray = path.split("/");
FileInfoQuery infoQuery = new FileInfoQuery();
infoQuery.setUserId(userId);
infoQuery.setFolderType(FileFolderTypeEnums.FOLDER.getType());
infoQuery.setFileIdArray(pathArray);
/**
* eg:
* StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
*/
// order by field("fileId1", "fileId2" ....)
String orderBy = "field(file_id,\"" + StringUtils.join(pathArray, "\",\"") + "\")";
infoQuery.setOrderBy(orderBy);
List<FileInfo> fileInfoList = fileInfoService.findListByParam(infoQuery);
return getSuccessResponseVO(CopyTools.copyList(fileInfoList, FolderVO.class));
}
protected ResponseVO createDownloadUrl(String fileId, String userId) {
FileInfo fileInfo = fileInfoService.getFileInfoByFileIdAndUserId(fileId, userId);
if (fileInfo == null) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
// 不能下载文件夹
if (FileFolderTypeEnums.FOLDER.getType().equals(fileInfo.getFolderType())) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
// fileId正常,得到50位随机code
String code = StringTools.getRandomString(Constants.LENGTH_50);
DownloadFileDto downloadFileDto = new DownloadFileDto();
downloadFileDto.setDownloadCode(code);
downloadFileDto.setFilePath(fileInfo.getFilePath());
downloadFileDto.setFileName(fileInfo.getFileName());
redisComponent.saveDownloadCode(code, downloadFileDto);
return getSuccessResponseVO(code);
}
protected void download(HttpServletRequest request, HttpServletResponse response, String code) throws Exception {
DownloadFileDto downloadFileDto = redisComponent.getDownloadCode(code);
if (downloadFileDto == null) {
return;
}
String filePath = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE
+ "/" + downloadFileDto.getFilePath();
String fileName = downloadFileDto.getFileName();
response.setContentType("application/x-msdownload; charset=UTF-8");
if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > 0) {//IE浏览器
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
}
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
readFile(response, filePath);
}
}
@@ -0,0 +1,83 @@
package com.easypan.entity.constants;
public class Constants {
public static final String SESSION_SHARE_KEY = "session_share_key_";
public static final String CHECK_CODE_KEY = "check_code_key";
public static final String CHECK_CODE_KEY_EMAIL = "check_code_key_email";
public static final int REGISTER_ZERO = 0;
public static final Integer LENGTH_5 = 5;
// redis中邮箱消息的键
public static final String REDIS_KEY_SYS_SETTING = "easypan:syssetting";
// 邮箱验证码过期时间
public static final Integer LENGTH_15 = 15;
// id长度
public static final Integer LENGTH_10 = 10;
// 1MB大小
public static final Long MB = 1024 * 1024L;
/**
* redis key 相关
*/
/**
* 过期时间 1分钟
*/
public static final Integer REDIS_KEY_EXPIRES_ONE_MIN = 60;
/**
* 过期时间 1天
*/
public static final Integer REDIS_KEY_EXPIRES_DAY = REDIS_KEY_EXPIRES_ONE_MIN * 60 * 24;
/**
* 过期时间 1 小时
*/
public static final Integer REDIS_KEY_EXPIRES_ONE_HOUR = REDIS_KEY_EXPIRES_ONE_MIN * 60;
/**
* 过期时间5分钟
*/
public static final Integer REDIS_KEY_EXPIRES_FIVE_MIN = REDIS_KEY_EXPIRES_ONE_MIN * 5;
public static final String REDIS_KEY_DOWNLOAD = "easypan:download:";
public static final String REDIS_KEY_USER_SPACE_USE = "easypan:user:spaceuse:";
public static final String REDIS_KEY_USER_FILE_TEMP_SIZE = "easypan:user:file:temp";
public static final String SESSION_KEY = "session_key";
// 头像
public static final String AVATAR_SUFFIX = ".jpg";
public static final String FILE_FOLDER_AVATAR_NAME = "/avatar";
public static final String AVATAR_DEFUALT = "default_avatar.jpg";
public static final String FILE_FOLDER_FILE = "/file";
public static final String FILE_FOLDER_TEMP = "/temp";
public static final String ORDER_RULE = "folder_type desc, last_update_time desc";
public static final String IMAGE_PNG_SUFFIX = ".png";
public static final Integer LENGTH_150 = 150;
public static final String TS_NAME = "index.ts";
public static final String M3U8_NAME = "index.m3u8";
public static final String ZERO_STR = "0";
public static final Integer LENGTH_50 = 50;
public static final Integer LENGTH_20 = 20;
}
@@ -0,0 +1,194 @@
package com.easypan.entity.dto;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
public class CreateImageCode {
// 图片的宽度。
private int width = 160;
// 图片的高度。
private int height = 40;
// 验证码字符个数
private int codeCount = 4;
// 验证码干扰线数
private int lineCount = 20;
// 验证码
private String code = null;
// 验证码图片Buffer
private BufferedImage buffImg = null;
Random random = new Random();
public CreateImageCode() {
creatImage();
}
public CreateImageCode(int width, int height) {
this.width = width;
this.height = height;
creatImage();
}
public CreateImageCode(int width, int height, int codeCount) {
this.width = width;
this.height = height;
this.codeCount = codeCount;
creatImage();
}
public CreateImageCode(int width, int height, int codeCount, int lineCount) {
this.width = width;
this.height = height;
this.codeCount = codeCount;
this.lineCount = lineCount;
creatImage();
}
// 生成图片
private void creatImage() {
int fontWidth = width / codeCount;// 字体的宽度
int fontHeight = height - 5;// 字体的高度
int codeY = height - 8;
// 图像buffer
buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = buffImg.getGraphics();
//Graphics2D g = buffImg.createGraphics();
// 设置背景色
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
// 设置字体
//Font font1 = getFont(fontHeight);
Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
g.setFont(font);
// 设置干扰线
for (int i = 0; i < lineCount; i++) {
int xs = random.nextInt(width);
int ys = random.nextInt(height);
int xe = xs + random.nextInt(width);
int ye = ys + random.nextInt(height);
g.setColor(getRandColor(1, 255));
g.drawLine(xs, ys, xe, ye);
}
// 添加噪点
float yawpRate = 0.01f;// 噪声率
int area = (int) (yawpRate * width * height);
for (int i = 0; i < area; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
buffImg.setRGB(x, y, random.nextInt(255));
}
String str1 = randomStr(codeCount);// 得到随机字符
this.code = str1;
for (int i = 0; i < codeCount; i++) {
String strRand = str1.substring(i, i + 1);
g.setColor(getRandColor(1, 255));
// g.drawString(a,x,y);
// a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处
g.drawString(strRand, i * fontWidth + 3, codeY);
}
}
// 得到随机字符
private String randomStr(int n) {
String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
String str2 = "";
int len = str1.length() - 1;
double r;
for (int i = 0; i < n; i++) {
r = (Math.random()) * len;
str2 = str2 + str1.charAt((int) r);
}
return str2;
}
// 得到随机颜色
private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色
if (fc > 255) fc = 255;
if (bc > 255) bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
/**
* 产生随机字体
*/
private Font getFont(int size) {
Random random = new Random();
Font font[] = new Font[5];
font[0] = new Font("Ravie", Font.PLAIN, size);
font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);
font[2] = new Font("Fixedsys", Font.PLAIN, size);
font[3] = new Font("Wide Latin", Font.PLAIN, size);
font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);
return font[random.nextInt(5)];
}
// 扭曲方法
private void shear(Graphics g, int w1, int h1, Color color) {
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);
}
private void shearX(Graphics g, int w1, int h1, Color color) {
int period = random.nextInt(2);
boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2);
for (int i = 0; i < h1; i++) {
double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap) {
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);
}
}
}
private void shearY(Graphics g, int w1, int h1, Color color) {
int period = random.nextInt(40) + 10; // 50;
boolean borderGap = true;
int frames = 20;
int phase = 7;
for (int i = 0; i < w1; i++) {
double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap) {
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);
}
}
}
public void write(OutputStream sos) throws IOException {
ImageIO.write(buffImg, "png", sos);
sos.close();
}
public BufferedImage getBuffImg() {
return buffImg;
}
public String getCode() {
return code.toLowerCase();
}
}
@@ -0,0 +1,10 @@
package com.easypan.entity.dto;
import lombok.Data;
@Data
public class DownloadFileDto {
private String downloadCode;
private String fileName;
private String filePath;
}
@@ -0,0 +1,13 @@
package com.easypan.entity.dto;
import lombok.Data;
import java.util.Date;
@Data
public class SessionShareDto {
private String shareId;
private String shareUserId;
private Date expireTime;
private String fileId;
}
@@ -0,0 +1,13 @@
package com.easypan.entity.dto;
import lombok.Data;
@Data
public class SessionWebUserDto {
private String nickName;
private String userId;
private Boolean isAdmin;
private Long useSpace;
private Long totalSpace;
private String avatar;
}
@@ -0,0 +1,30 @@
package com.easypan.entity.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class SysSettingsDto implements Serializable {
/**
* 注册发送邮件标题
*/
private String registerEmailTitle = "邮箱验证码";
/**
* 注册发送邮件内容
*/
private String registerEmailContent = "你好,您的邮箱验证码是:%s,15分钟有效";
/**
* 用户初始化空间大小 5M
*/
private Integer userInitUseSpace = 5;
}
@@ -0,0 +1,13 @@
package com.easypan.entity.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.io.Serializable;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class UploadResultDto implements Serializable {
private String fileId;
private String status;
}
@@ -0,0 +1,14 @@
package com.easypan.entity.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class UserSpaceDto implements Serializable {
private Long useSpace;
private Long totalSpace;
}
@@ -0,0 +1,16 @@
package com.easypan.entity.enums;
public enum DateTimePatternEnum {
YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"), YYYY_MM_DD("yyyy-MM-dd"), YYYYMM("yyyyMM");
private String pattern;
DateTimePatternEnum(String pattern) {
this.pattern = pattern;
}
public String getPattern() {
return pattern;
}
}
@@ -0,0 +1,37 @@
package com.easypan.entity.enums;
public enum FileCategoryEnums {
VIDEO(1, "video", "视频"),
MUSIC(2, "music", "音频"),
IMAGE(3, "image", "图片"),
DOC(4, "doc", "文档"),
OTHERS(5, "others", "其他");
private Integer category;
private String code;
private String desc;
FileCategoryEnums(Integer category, String code, String desc) {
this.category = category;
this.code = code;
this.desc = desc;
}
public static FileCategoryEnums getByCode(String code) {
for (FileCategoryEnums item : FileCategoryEnums.values()) {
if (item.getCode().equals(code)) {
return item;
}
}
return null;
}
public Integer getCategory() {
return category;
}
public String getCode() {
return code;
}
}
@@ -0,0 +1,24 @@
package com.easypan.entity.enums;
public enum FileDelFlagEnums {
DEL(0, "删除"),
RECYCLE (1, "回收站"),
USING(2, "使用中");;
private Integer flag;
private String desc;
FileDelFlagEnums(Integer flag, String desc) {
this.flag = flag;
this.desc = desc;
}
public Integer getFlag() {
return flag;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,23 @@
package com.easypan.entity.enums;
public enum FileFolderTypeEnums {
FILE(0, "文件"),
FOLDER(1, "目录");
private Integer type;
private String desc;
FileFolderTypeEnums(Integer type, String desc) {
this.type = type;
this.desc = desc;
}
public Integer getType() {
return type;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,24 @@
package com.easypan.entity.enums;
public enum FileStatusEnums {
TRANSFER(0, "转码中"),
TRANSFER_FAIL(1, "转码失败"),
USING(2, "使用中");
private Integer status;
private String desc;
FileStatusEnums(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,66 @@
package com.easypan.entity.enums;
import org.apache.commons.lang3.ArrayUtils;
public enum FileTypeEnums {
//1:视频 2:音频 3:图片 4:pdf 5:word 6:excel 7:txt 8:code 9:zip 10:其他文件
VIDEO(FileCategoryEnums.VIDEO, 1, new String[]{".mp4", ".avi", ".rmvb", ".mkv", ".mov"}, "视频"),
MUSIC(FileCategoryEnums.MUSIC, 2, new String[]{".mp3", ".wav", ".wma", ".mp2", ".flac", ".midi", ".ra", ".ape", ".aac", ".cda"}, "音频"),
IMAGE(FileCategoryEnums.IMAGE, 3, new String[]{".jpeg", ".jpg", ".png", ".gif", ".bmp", ".dds", ".psd", ".pdt", ".webp", ".xmp", ".svg", ".tiff"}, "图片"),
PDF(FileCategoryEnums.DOC, 4, new String[]{".pdf", ".pptx"}, "pdf"),
WORD(FileCategoryEnums.DOC, 5, new String[]{".docx"}, "word"),
EXCEL(FileCategoryEnums.DOC, 6, new String[]{".xlsx"}, "excel"),
TXT(FileCategoryEnums.DOC, 7, new String[]{".txt"}, "txt文本"),
PROGRAME(FileCategoryEnums.OTHERS, 8, new String[]{".h", ".c", ".hpp", ".hxx", ".cpp", ".cc", ".c++", ".cxx", ".m", ".o", ".s", ".dll", ".cs",
".java", ".class", ".js", ".ts", ".css", ".scss", ".vue", ".jsx", ".sql", ".md", ".json", ".html", ".xml"}, "CODE"),
ZIP(FileCategoryEnums.OTHERS, 9, new String[]{"rar", ".zip", ".7z", ".cab", ".arj", ".lzh", ".tar", ".gz", ".ace", ".uue", ".bz", ".jar", ".iso",
".mpq"}, "压缩包"),
OTHERS(FileCategoryEnums.OTHERS, 10, new String[]{}, "其他");
private FileCategoryEnums category;
private Integer type;
private String[] suffixs;
private String desc;
FileTypeEnums(FileCategoryEnums category, Integer type, String[] suffixs, String desc) {
this.category = category;
this.type = type;
this.suffixs = suffixs;
this.desc = desc;
}
public static FileTypeEnums getFileTypeBySuffix(String suffix) {
for (FileTypeEnums item : FileTypeEnums.values()) {
if (ArrayUtils.contains(item.getSuffixs(), suffix)) {
return item;
}
}
return FileTypeEnums.OTHERS;
}
public static FileTypeEnums getByType(Integer type) {
for (FileTypeEnums item : FileTypeEnums.values()) {
if (item.getType().equals(type)) {
return item;
}
}
return null;
}
public String[] getSuffixs() {
return suffixs;
}
public FileCategoryEnums getCategory() {
return category;
}
public Integer getType() {
return type;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,15 @@
package com.easypan.entity.enums;
public enum PageSize {
SIZE15(15), SIZE20(20), SIZE30(30), SIZE40(40), SIZE50(50);
int size;
private PageSize(int size) {
this.size = size;
}
public int getSize() {
return this.size;
}
}
@@ -0,0 +1,30 @@
package com.easypan.entity.enums;
public enum ResponseCodeEnum {
CODE_200(200, "请求成功"),
CODE_404(404, "请求地址不存在"),
CODE_600(600, "请求参数错误"),
CODE_601(601, "信息已经存在"),
CODE_500(500, "服务器返回错误,请联系管理员"),
CODE_901(901, "登录超时,请重新登录"),
CODE_902(902, "分享连接不存在,或者已失效"),
CODE_903(903, "分享验证失效,请重新验证"),
CODE_904(904, "网盘空间不足,请扩容");
private Integer code;
private String msg;
ResponseCodeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
@@ -0,0 +1,41 @@
package com.easypan.entity.enums;
public enum ShareValidTypeEnums {
DAY_1(0, 1, "1天"),
DAY_7(1, 7, "7天"),
DAY_30(2, 30, "30天"),
FOREVER(3, -1, "永久有效");
private Integer type;
private Integer days;
private String desc;
ShareValidTypeEnums(Integer type, Integer days, String desc) {
this.type = type;
this.days = days;
this.desc = desc;
}
public static ShareValidTypeEnums getByType(Integer type) {
for (ShareValidTypeEnums typeEnums : ShareValidTypeEnums.values()) {
if (typeEnums.getType().equals(type)) {
return typeEnums;
}
}
return null;
}
public Integer getType() {
return type;
}
public Integer getDays() {
return days;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,24 @@
package com.easypan.entity.enums;
public enum UploadStatusEnums {
UPLOAD_SECONDS("upload_seconds", "秒传"),
UPLOADING("uploading", "上传中"),
UPLOAD_FINISH("upload_finish", "上传完成");
private String code;
private String desc;
UploadStatusEnums(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,38 @@
package com.easypan.entity.enums;
public enum UserStatusEnum {
DISABLE(0, "禁用"),
ENABLE(1, "启用");
private Integer status;
private String desc;
UserStatusEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public static UserStatusEnum getByStatus(Integer status) {
for (UserStatusEnum item : UserStatusEnum.values()) {
if (item.getStatus().equals(status)) {
return item;
}
}
return null;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
@@ -0,0 +1,24 @@
package com.easypan.entity.enums;
//正则校验
public enum VerifyRegexEnum {
NO("", "不校验"),
EMAIL("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$", "邮箱"),
PASSWORD("^(?=.*\\d)(?=.*[a-zA-Z])[\\da-zA-Z~!@#$%^&*_]{8,}$", "只能是数字,字母,特殊字符 8-18位");
private String regex;
private String desc;
VerifyRegexEnum(String regex, String desc) {
this.regex = regex;
this.desc = desc;
}
public String getRegex() {
return regex;
}
public String getDesc() {
return desc;
}
}
@@ -0,0 +1,38 @@
package com.easypan.entity.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 邮箱验证码
*/
@Data
public class EmailCode implements Serializable {
/**
* 邮箱
*/
private String email;
/**
* 编号
*/
private String code;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 0:未使用 1:已使用
*/
private Integer status;
}
@@ -0,0 +1,106 @@
package com.easypan.entity.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 文件信息
*/
@Data
public class FileInfo implements Serializable {
/**
* 文件ID
*/
private String fileId;
/**
* 用户ID
*/
private String userId;
/**
* md5值,第一次上传记录
*/
private String fileMd5;
/**
* 父级ID
*/
private String filePid;
/**
* 文件大小
*/
private Long fileSize;
/**
* 文件名称
*/
private String fileName;
/**
* 封面
*/
private String fileCover;
/**
* 文件路径
*/
private String filePath;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 最后更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lastUpdateTime;
/**
* 0:文件 1:目录
*/
private Integer folderType;
/**
* 1:视频 2:音频 3:图片 4:文档 5:其他
*/
private Integer fileCategory;
/**
* 1:视频 2:音频 3:图片 4:pdf 5:doc 6:excel 7:txt 8:code 9:zip 10:其他
*/
private Integer fileType;
/**
* 0:转码中 1转码失败 2:转码成功
*/
private Integer status;
/**
* 回收站时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date recoveryTime;
/**
* 删除标记 0:删除 1:回收站 2:正常
*/
private Integer delFlag;
private String nickName;
}
@@ -0,0 +1,84 @@
package com.easypan.entity.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 分享信息
*/
@Data
public class FileShare implements Serializable {
/**
* 分享ID
*/
private String shareId;
/**
* 文件ID
*/
private String fileId;
/**
* 用户ID
*/
private String userId;
/**
* 有效期类型 0:1天 1:7天 2:30天 3:永久有效
*/
private Integer validType;
/**
* 失效时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expireTime;
/**
* 分享时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date shareTime;
/**
* 提取码
*/
private String code;
/**
* 浏览次数
*/
private Integer showCount;
private String fileName;
/**
* 0:文件 1:目录
*/
private Integer folderType;
/**
* 1:视频 2:音频 3:图片 4:文档 5:其他
*/
private Integer fileCategory;
/**
* 1:视频 2:音频 3:图片 4:pdf 5:doc 6:excel 7:txt 8:code 9:zip 10:其他
*/
private Integer fileType;
/**
* 封面
*/
private String fileCover;
}
@@ -0,0 +1,76 @@
package com.easypan.entity.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 用户信息
*/
@Data
public class UserInfo implements Serializable {
/**
* 用户ID
*/
private String userId;
/**
* 昵称
*/
private String nickName;
/**
* 邮箱
*/
private String email;
/**
* qq 头像
*/
private String qqAvatar;
/**
* qq openID
*/
private String qqOpenId;
/**
* 密码
*/
private String password;
/**
* 加入时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date joinTime;
/**
* 最后登录时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lastLoginTime;
/**
* 0:禁用 1:正常
*/
private Integer status;
/**
* 使用空间单位byte
*/
private Long useSpace;
/**
* 总空间单位byte
*/
private Long totalSpace;
}
@@ -0,0 +1,40 @@
package com.easypan.entity.query;
public class BaseParam {
private SimplePage simplePage;
private Integer pageNo;
private Integer pageSize;
private String orderBy;
public SimplePage getSimplePage() {
return simplePage;
}
public void setSimplePage(SimplePage simplePage) {
this.simplePage = simplePage;
}
public Integer getPageNo() {
return pageNo;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public void setOrderBy(String orderBy){
this.orderBy = orderBy;
}
public String getOrderBy(){
return this.orderBy;
}
}
@@ -0,0 +1,103 @@
package com.easypan.entity.query;
/**
* 邮箱验证码参数
*/
public class EmailCodeQuery extends BaseParam {
/**
* 邮箱
*/
private String email;
private String emailFuzzy;
/**
* 编号
*/
private String code;
private String codeFuzzy;
/**
* 创建时间
*/
private String createTime;
private String createTimeStart;
private String createTimeEnd;
/**
* 0:未使用 1:已使用
*/
private Integer status;
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return this.email;
}
public void setEmailFuzzy(String emailFuzzy) {
this.emailFuzzy = emailFuzzy;
}
public String getEmailFuzzy() {
return this.emailFuzzy;
}
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return this.code;
}
public void setCodeFuzzy(String codeFuzzy) {
this.codeFuzzy = codeFuzzy;
}
public String getCodeFuzzy() {
return this.codeFuzzy;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getCreateTime() {
return this.createTime;
}
public void setCreateTimeStart(String createTimeStart) {
this.createTimeStart = createTimeStart;
}
public String getCreateTimeStart() {
return this.createTimeStart;
}
public void setCreateTimeEnd(String createTimeEnd) {
this.createTimeEnd = createTimeEnd;
}
public String getCreateTimeEnd() {
return this.createTimeEnd;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getStatus() {
return this.status;
}
}
@@ -0,0 +1,128 @@
package com.easypan.entity.query;
import lombok.Data;
/**
* 文件信息参数
*/
@Data
public class FileInfoQuery extends BaseParam {
/**
* 文件ID
*/
private String fileId;
private String fileIdFuzzy;
/**
* 用户ID
*/
private String userId;
private String userIdFuzzy;
/**
* md5值,第一次上传记录
*/
private String fileMd5;
private String fileMd5Fuzzy;
/**
* 父级ID
*/
private String filePid;
private String filePidFuzzy;
/**
* 文件大小
*/
private Long fileSize;
/**
* 文件名称
*/
private String fileName;
private String fileNameFuzzy;
/**
* 封面
*/
private String fileCover;
private String fileCoverFuzzy;
/**
* 文件路径
*/
private String filePath;
private String filePathFuzzy;
/**
* 创建时间
*/
private String createTime;
private String createTimeStart;
private String createTimeEnd;
/**
* 最后更新时间
*/
private String lastUpdateTime;
private String lastUpdateTimeStart;
private String lastUpdateTimeEnd;
/**
* 0:文件 1:目录
*/
private Integer folderType;
/**
* 1:视频 2:音频 3:图片 4:文档 5:其他
*/
private Integer fileCategory;
/**
* 1:视频 2:音频 3:图片 4:pdf 5:doc 6:excel 7:txt 8:code 9:zip 10:其他
*/
private Integer fileType;
/**
* 0:转码中 1转码失败 2:转码成功
*/
private Integer status;
/**
* 回收站时间
*/
private String recoveryTime;
private String recoveryTimeStart;
private String recoveryTimeEnd;
/**
* 删除标记 0:删除 1:回收站 2:正常
*/
private Integer delFlag;
private String[] fileIdArray;
private String[] filePidArray;
private String[] excludeFileIdArray;
private Boolean queryExpire;
private Boolean queryNickName;
}
@@ -0,0 +1,203 @@
package com.easypan.entity.query;
/**
* 分享信息参数
*/
public class FileShareQuery extends BaseParam {
/**
* 分享ID
*/
private String shareId;
private String shareIdFuzzy;
/**
* 文件ID
*/
private String fileId;
private String fileIdFuzzy;
/**
* 用户ID
*/
private String userId;
private String userIdFuzzy;
/**
* 有效期类型 0:1天 1:7天 2:30天 3:永久有效
*/
private Integer validType;
/**
* 失效时间
*/
private String expireTime;
private String expireTimeStart;
private String expireTimeEnd;
/**
* 分享时间
*/
private String shareTime;
private String shareTimeStart;
private String shareTimeEnd;
/**
* 提取码
*/
private String code;
private String codeFuzzy;
/**
* 浏览次数
*/
private Integer showCount;
private Boolean queryFileName;
public Boolean getQueryFileName() {
return queryFileName;
}
public void setQueryFileName(Boolean queryFileName) {
this.queryFileName = queryFileName;
}
public void setShareId(String shareId) {
this.shareId = shareId;
}
public String getShareId() {
return this.shareId;
}
public void setShareIdFuzzy(String shareIdFuzzy) {
this.shareIdFuzzy = shareIdFuzzy;
}
public String getShareIdFuzzy() {
return this.shareIdFuzzy;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
public String getFileId() {
return this.fileId;
}
public void setFileIdFuzzy(String fileIdFuzzy) {
this.fileIdFuzzy = fileIdFuzzy;
}
public String getFileIdFuzzy() {
return this.fileIdFuzzy;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserId() {
return this.userId;
}
public void setUserIdFuzzy(String userIdFuzzy) {
this.userIdFuzzy = userIdFuzzy;
}
public String getUserIdFuzzy() {
return this.userIdFuzzy;
}
public void setValidType(Integer validType) {
this.validType = validType;
}
public Integer getValidType() {
return this.validType;
}
public void setExpireTime(String expireTime) {
this.expireTime = expireTime;
}
public String getExpireTime() {
return this.expireTime;
}
public void setExpireTimeStart(String expireTimeStart) {
this.expireTimeStart = expireTimeStart;
}
public String getExpireTimeStart() {
return this.expireTimeStart;
}
public void setExpireTimeEnd(String expireTimeEnd) {
this.expireTimeEnd = expireTimeEnd;
}
public String getExpireTimeEnd() {
return this.expireTimeEnd;
}
public void setShareTime(String shareTime) {
this.shareTime = shareTime;
}
public String getShareTime() {
return this.shareTime;
}
public void setShareTimeStart(String shareTimeStart) {
this.shareTimeStart = shareTimeStart;
}
public String getShareTimeStart() {
return this.shareTimeStart;
}
public void setShareTimeEnd(String shareTimeEnd) {
this.shareTimeEnd = shareTimeEnd;
}
public String getShareTimeEnd() {
return this.shareTimeEnd;
}
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return this.code;
}
public void setCodeFuzzy(String codeFuzzy) {
this.codeFuzzy = codeFuzzy;
}
public String getCodeFuzzy() {
return this.codeFuzzy;
}
public void setShowCount(Integer showCount) {
this.showCount = showCount;
}
public Integer getShowCount() {
return this.showCount;
}
}
@@ -0,0 +1,101 @@
package com.easypan.entity.query;
import com.easypan.entity.enums.PageSize;
public class SimplePage {
private int pageNo;
private int countTotal;
private int pageSize;
private int pageTotal;
private int start;
private int end;
public SimplePage() {
}
public SimplePage(Integer pageNo, int countTotal, int pageSize) {
if (null == pageNo) {
pageNo = 0;
}
this.pageNo = pageNo;
this.countTotal = countTotal;
this.pageSize = pageSize;
action();
}
public SimplePage(int start, int end) {
this.start = start;
this.end = end;
}
public void action() {
if (this.pageSize <= 0) {
this.pageSize = PageSize.SIZE20.getSize();
}
if (this.countTotal > 0) {
this.pageTotal = this.countTotal % this.pageSize == 0 ? this.countTotal / this.pageSize
: this.countTotal / this.pageSize + 1;
} else {
pageTotal = 1;
}
if (pageNo <= 1) {
pageNo = 1;
}
if (pageNo > pageTotal) {
pageNo = pageTotal;
}
this.start = (pageNo - 1) * pageSize;
this.end = this.pageSize;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public int getPageTotal() {
return pageTotal;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public void setPageTotal(int pageTotal) {
this.pageTotal = pageTotal;
}
public int getCountTotal() {
return countTotal;
}
public int getPageSize() {
return pageSize;
}
public void setStart(int start) {
this.start = start;
}
public void setEnd(int end) {
this.end = end;
}
public void setCountTotal(int countTotal) {
this.countTotal = countTotal;
this.action();
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
@@ -0,0 +1,254 @@
package com.easypan.entity.query;
/**
*
* 用户信息参数
*
*/
public class UserInfoQuery extends BaseParam {
/**
* 用户ID
*/
private String userId;
private String userIdFuzzy;
/**
* 昵称
*/
private String nickName;
private String nickNameFuzzy;
/**
* 邮箱
*/
private String email;
private String emailFuzzy;
/**
*
*/
private String qqAvatar;
private String qqAvatarFuzzy;
/**
*
*/
private String qqOpenId;
private String qqOpenIdFuzzy;
/**
* 密码
*/
private String password;
private String passwordFuzzy;
/**
* 加入时间
*/
private String joinTime;
private String joinTimeStart;
private String joinTimeEnd;
/**
* 最后登录时间
*/
private String lastLoginTime;
private String lastLoginTimeStart;
private String lastLoginTimeEnd;
/**
* 0:禁用 1:正常
*/
private Integer status;
/**
*
*/
private Long useSpace;
/**
*
*/
private Long totalSpace;
public void setUserId(String userId){
this.userId = userId;
}
public String getUserId(){
return this.userId;
}
public void setUserIdFuzzy(String userIdFuzzy){
this.userIdFuzzy = userIdFuzzy;
}
public String getUserIdFuzzy(){
return this.userIdFuzzy;
}
public void setNickName(String nickName){
this.nickName = nickName;
}
public String getNickName(){
return this.nickName;
}
public void setNickNameFuzzy(String nickNameFuzzy){
this.nickNameFuzzy = nickNameFuzzy;
}
public String getNickNameFuzzy(){
return this.nickNameFuzzy;
}
public void setEmail(String email){
this.email = email;
}
public String getEmail(){
return this.email;
}
public void setEmailFuzzy(String emailFuzzy){
this.emailFuzzy = emailFuzzy;
}
public String getEmailFuzzy(){
return this.emailFuzzy;
}
public void setQqAvatar(String qqAvatar){
this.qqAvatar = qqAvatar;
}
public String getQqAvatar(){
return this.qqAvatar;
}
public void setQqAvatarFuzzy(String qqAvatarFuzzy){
this.qqAvatarFuzzy = qqAvatarFuzzy;
}
public String getQqAvatarFuzzy(){
return this.qqAvatarFuzzy;
}
public void setQqOpenId(String qqOpenId){
this.qqOpenId = qqOpenId;
}
public String getQqOpenId(){
return this.qqOpenId;
}
public void setQqOpenIdFuzzy(String qqOpenIdFuzzy){
this.qqOpenIdFuzzy = qqOpenIdFuzzy;
}
public String getQqOpenIdFuzzy(){
return this.qqOpenIdFuzzy;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword(){
return this.password;
}
public void setPasswordFuzzy(String passwordFuzzy){
this.passwordFuzzy = passwordFuzzy;
}
public String getPasswordFuzzy(){
return this.passwordFuzzy;
}
public void setJoinTime(String joinTime){
this.joinTime = joinTime;
}
public String getJoinTime(){
return this.joinTime;
}
public void setJoinTimeStart(String joinTimeStart){
this.joinTimeStart = joinTimeStart;
}
public String getJoinTimeStart(){
return this.joinTimeStart;
}
public void setJoinTimeEnd(String joinTimeEnd){
this.joinTimeEnd = joinTimeEnd;
}
public String getJoinTimeEnd(){
return this.joinTimeEnd;
}
public void setLastLoginTime(String lastLoginTime){
this.lastLoginTime = lastLoginTime;
}
public String getLastLoginTime(){
return this.lastLoginTime;
}
public void setLastLoginTimeStart(String lastLoginTimeStart){
this.lastLoginTimeStart = lastLoginTimeStart;
}
public String getLastLoginTimeStart(){
return this.lastLoginTimeStart;
}
public void setLastLoginTimeEnd(String lastLoginTimeEnd){
this.lastLoginTimeEnd = lastLoginTimeEnd;
}
public String getLastLoginTimeEnd(){
return this.lastLoginTimeEnd;
}
public void setStatus(Integer status){
this.status = status;
}
public Integer getStatus(){
return this.status;
}
public void setUseSpace(Long useSpace){
this.useSpace = useSpace;
}
public Long getUseSpace(){
return this.useSpace;
}
public void setTotalSpace(Long totalSpace){
this.totalSpace = totalSpace;
}
public Long getTotalSpace(){
return this.totalSpace;
}
}
@@ -0,0 +1,64 @@
package com.easypan.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class FileInfoVO {
/**
* 文件ID
*/
private String fileId;
/**
* 父级ID
*/
private String filePid;
/**
* 文件大小
*/
private Long fileSize;
/**
* 文件名称
*/
private String fileName;
/**
* 封面
*/
private String fileCover;
/**
* 最后更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lastUpdateTime;
/**
* 0:文件 1:目录
*/
private Integer folderType;
/**
* 1:视频 2:音频 3:图片 4:文档 5:其他
*/
private Integer fileCategory;
/**
* 1:视频 2:音频 3:图片 4:pdf 5:doc 6:excel 7:txt 8:code 9:zip 10:其他
*/
private Integer fileType;
/**
* 0:转码中 1转码失败 2:转码成功
*/
private Integer status;
}
@@ -0,0 +1,10 @@
package com.easypan.entity.vo;
import lombok.Data;
@Data
public class FolderVO {
private String fileName;
private String fileId;
}
@@ -0,0 +1,78 @@
package com.easypan.entity.vo;
import java.util.ArrayList;
import java.util.List;
public class PaginationResultVO<T> {
private Integer totalCount;
private Integer pageSize;
private Integer pageNo;
private Integer pageTotal;
private List<T> list = new ArrayList<T>();
public PaginationResultVO(Integer totalCount, Integer pageSize, Integer pageNo, List<T> list) {
this.totalCount = totalCount;
this.pageSize = pageSize;
this.pageNo = pageNo;
this.list = list;
}
public PaginationResultVO(Integer totalCount, Integer pageSize, Integer pageNo, Integer pageTotal, List<T> list) {
if (pageNo == 0) {
pageNo = 1;
}
this.totalCount = totalCount;
this.pageSize = pageSize;
this.pageNo = pageNo;
this.pageTotal = pageTotal;
this.list = list;
}
public PaginationResultVO(List<T> list) {
this.list = list;
}
public PaginationResultVO() {
}
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getPageNo() {
return pageNo;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public Integer getPageTotal() {
return pageTotal;
}
public void setPageTotal(Integer pageTotal) {
this.pageTotal = pageTotal;
}
}
@@ -0,0 +1,41 @@
package com.easypan.entity.vo;
public class ResponseVO<T> {
private String status;
private Integer code;
private String info;
private T data;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
@@ -0,0 +1,21 @@
package com.easypan.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class ShareInfoVO {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date shareTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date expireTime;
private String nickName;
private String fileName;
private Boolean currentUser;
private String fileId;
private String avatar;
private String userId;
}
@@ -0,0 +1,136 @@
package com.easypan.entity.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* 用户信息
*/
public class UserInfoVO implements Serializable {
/**
* 用户ID
*/
private String userId;
/**
* 昵称
*/
private String nickName;
/**
* 邮箱
*/
private String email;
/**
* qq 头像
*/
private String qqAvatar;
/**
* 加入时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date joinTime;
/**
* 最后登录时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date lastLoginTime;
/**
* 0:禁用 1:正常
*/
private Integer status;
/**
* 使用空间单位byte
*/
private Long useSpace;
/**
* 总空间单位byte
*/
private Long totalSpace;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getQqAvatar() {
return qqAvatar;
}
public void setQqAvatar(String qqAvatar) {
this.qqAvatar = qqAvatar;
}
public Date getJoinTime() {
return joinTime;
}
public void setJoinTime(Date joinTime) {
this.joinTime = joinTime;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Long getUseSpace() {
return useSpace;
}
public void setUseSpace(Long useSpace) {
this.useSpace = useSpace;
}
public Long getTotalSpace() {
return totalSpace;
}
public void setTotalSpace(Long totalSpace) {
this.totalSpace = totalSpace;
}
}
@@ -0,0 +1,61 @@
package com.easypan.exception;
import com.easypan.entity.enums.ResponseCodeEnum;
public class BusinessException extends RuntimeException {
private ResponseCodeEnum codeEnum;
private Integer code;
private String message;
public BusinessException(String message, Throwable e) {
super(message, e);
this.message = message;
}
public BusinessException(String message) {
super(message);
this.message = message;
}
public BusinessException(Throwable e) {
super(e);
}
public BusinessException(ResponseCodeEnum codeEnum) {
super(codeEnum.getMsg());
this.codeEnum = codeEnum;
this.code = codeEnum.getCode();
this.message = codeEnum.getMsg();
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
this.message = message;
}
public ResponseCodeEnum getCodeEnum() {
return codeEnum;
}
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
/**
* 重写fillInStackTrace 业务异常不需要堆栈信息,提高效率.
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}
@@ -0,0 +1,42 @@
package com.easypan.mappers;
import org.apache.ibatis.annotations.Param;
import java.util.List;
interface BaseMapper<T, P> {
/**
* insert:(插入). <br/>
*/
Integer insert(@Param("bean") T t);
/**
* insertOrUpdate:(插入或者更新). <br/>
*/
Integer insertOrUpdate(@Param("bean") T t);
/**
* insertBatch:(批量插入). <br/>
*/
Integer insertBatch(@Param("list") List<T> list);
/**
* insertOrUpdateBatch:(批量插入或更新). <br/>
*/
Integer insertOrUpdateBatch(@Param("list") List<T> list);
/**
* selectList:(根据参数查询集合). <br/>
*/
List<T> selectList(@Param("query") P p);
/**
* selectCount:(根据集合查询数量). <br/>
*/
Integer selectCount(@Param("query") P p);
}
@@ -0,0 +1,29 @@
package com.easypan.mappers;
import org.apache.ibatis.annotations.Param;
/**
* 邮箱验证码 数据库操作接口
*/
public interface EmailCodeMapper<T, P> extends BaseMapper<T, P> {
/**
* 根据EmailAndCode更新
*/
Integer updateByEmailAndCode(@Param("bean") T t, @Param("email") String email, @Param("code") String code);
/**
* 根据EmailAndCode删除
*/
Integer deleteByEmailAndCode(@Param("email") String email, @Param("code") String code);
/**
* 根据EmailAndCode获取对象
*/
T selectByEmailAndCode(@Param("email") String email, @Param("code") String code);
void disableEmailCode(@Param("email") String email);
}
@@ -0,0 +1,50 @@
package com.easypan.mappers;
import com.easypan.entity.po.FileInfo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 文件信息 数据库操作接口
*/
public interface FileInfoMapper<T, P> extends BaseMapper<T, P> {
/**
* 根据FileIdAndUserId更新
*/
Integer updateByFileIdAndUserId(@Param("bean") T t, @Param("fileId") String fileId, @Param("userId") String userId);
/**
* 根据FileIdAndUserId删除
*/
Integer deleteByFileIdAndUserId(@Param("fileId") String fileId, @Param("userId") String userId);
/**
* 根据FileIdAndUserId获取对象
*/
T selectByFileIdAndUserId(@Param("fileId") String fileId, @Param("userId") String userId);
void updateFileStatusWithOldStatus(@Param("fileId") String fileId, @Param("userId") String userId, @Param("bean") T t,
@Param("oldStatus") Integer oldStatus);
void updateFileDelFlagBatch(@Param("bean") FileInfo fileInfo,
@Param("userId") String userId,
@Param("filePidList") List<String> filePidList,
@Param("fileIdList") List<String> fileIdList,
@Param("oldDelFlag") Integer oldDelFlag);
void delFileBatch(@Param("userId") String userId,
@Param("filePidList") List<String> filePidList,
@Param("fileIdList") List<String> fileIdList,
@Param("oldDelFlag") Integer oldDelFlag);
Long selectUseSpace(@Param("userId") String userId);
void deleteFileByUserId(@Param("userId") String userId);
}
@@ -0,0 +1,30 @@
package com.easypan.mappers;
import org.apache.ibatis.annotations.Param;
/**
* 分享信息 数据库操作接口
*/
public interface FileShareMapper<T, P> extends BaseMapper<T, P> {
/**
* 根据ShareId更新
*/
Integer updateByShareId(@Param("bean") T t, @Param("shareId") String shareId);
/**
* 根据ShareId删除
*/
Integer deleteByShareId(@Param("shareId") String shareId);
/**
* 根据ShareId获取对象
*/
T selectByShareId(@Param("shareId") String shareId);
Integer deleteFileShareBatch(@Param("shareIdArray") String[] shareIdArray, @Param("userId") String userId);
void updateShareShowCount(@Param("shareId") String shareId);
}
@@ -0,0 +1,85 @@
package com.easypan.mappers;
import com.easypan.entity.po.UserInfo;
import org.apache.ibatis.annotations.Param;
/**
* 用户信息 数据库操作接口
*/
public interface UserInfoMapper<T, P> extends BaseMapper<T, P> {
/**
* 根据UserId更新
*/
Integer updateByUserId(@Param("bean") T t, @Param("userId") String userId);
/**
* 根据UserId删除
*/
Integer deleteByUserId(@Param("userId") String userId);
/**
* 根据UserId获取对象
*/
T selectByUserId(@Param("userId") String userId);
/**
* 根据Email更新
*/
Integer updateByEmail(@Param("bean") T t, @Param("email") String email);
/**
* 根据Email删除
*/
Integer deleteByEmail(@Param("email") String email);
/**
* 根据Email获取对象
*/
T selectByEmail(@Param("email") String email);
/**
* 根据NickName更新
*/
Integer updateByNickName(@Param("bean") T t, @Param("nickName") String nickName);
/**
* 根据NickName删除
*/
Integer deleteByNickName(@Param("nickName") String nickName);
/**
* 根据NickName获取对象
*/
T selectByNickName(@Param("nickName") String nickName);
/**
* 根据QqOpenId更新
*/
Integer updateByQqOpenId(@Param("bean") T t, @Param("qqOpenId") String qqOpenId);
/**
* 根据QqOpenId删除
*/
Integer deleteByQqOpenId(@Param("qqOpenId") String qqOpenId);
/**
* 根据QqOpenId获取对象
*/
T selectByQqOpenId(@Param("qqOpenId") String qqOpenId);
Integer updateUserSpace(@Param("userId") String userId, @Param("useSpace") Long useSpace, @Param("totalSpace") Long totalSpace);
}
@@ -0,0 +1,11 @@
package com.easypan.service;
/**
* 邮箱验证码 业务接口
*/
public interface EmailCodeService {
void sendEmailCode(String toEmail, Integer type);
void checkCode(String email, String code);
}
@@ -0,0 +1,48 @@
package com.easypan.service;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.dto.UploadResultDto;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.vo.PaginationResultVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 文件信息 业务接口
*/
public interface FileInfoService {
FileInfo rename(String fileId, String userId, String fileName);
PaginationResultVO<FileInfo> findListByPage(FileInfoQuery param);
UploadResultDto uploadFile(SessionWebUserDto webUserDto, String fileId, MultipartFile file,
String fileName, String filePid, String fileMd5, Integer chunkIndex, Integer chunks);
FileInfo getFileInfoByFileIdAndUserId(String realFileId, String userId);
FileInfo newFolder(String filePid, String userId, String fileName);
List<FileInfo> findListByParam(FileInfoQuery param);
List<FileInfo> loadAllFolder(String userId, String filePid, String currentFileIds);
void changeFileFolder(String fileIds, String filePid, String userId);
void removeFile2RecycleBatch(String userId, String fileIds);
void recoverFileBatch(String userId, String fileIds);
void delFileBatch(String userId, String fileIds, boolean b);
void saveShare(String shareRootFilePid, String shareFileIds, String myFolderId, String shareUserId, String currentUserId);
void deleteFileByUserId(String userId);
}
@@ -0,0 +1,69 @@
package com.easypan.service;
import com.easypan.entity.dto.SessionShareDto;
import com.easypan.entity.po.FileShare;
import com.easypan.entity.query.FileShareQuery;
import com.easypan.entity.vo.PaginationResultVO;
import java.util.List;
/**
* 分享信息 业务接口
*/
public interface FileShareService {
/**
* 根据条件查询列表
*/
List<FileShare> findListByParam(FileShareQuery param);
/**
* 根据条件查询列表
*/
Integer findCountByParam(FileShareQuery param);
/**
* 分页查询
*/
PaginationResultVO<FileShare> findListByPage(FileShareQuery param);
/**
* 新增
*/
Integer add(FileShare bean);
/**
* 批量新增
*/
Integer addBatch(List<FileShare> listBean);
/**
* 批量新增/修改
*/
Integer addOrUpdateBatch(List<FileShare> listBean);
/**
* 根据ShareId查询对象
*/
FileShare getFileShareByShareId(String shareId);
/**
* 根据ShareId修改
*/
Integer updateFileShareByShareId(FileShare bean, String shareId);
/**
* 根据ShareId删除
*/
Integer deleteFileShareByShareId(String shareId);
void deleteFileShareBatch(String[] shareIdArray, String userId);
void saveShare(FileShare share);
SessionShareDto checkShareCode(String shareId, String code);
}
@@ -0,0 +1,37 @@
package com.easypan.service;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.query.UserInfoQuery;
import com.easypan.entity.vo.PaginationResultVO;
import java.util.List;
/**
* 用户信息 业务接口
*/
public interface UserInfoService {
void register(String email, String nickName, String password, String emailCode);
SessionWebUserDto login(String email, String password);
void resetPwd(String email, String password, String emailCode);
void updateUserInfoByUserId(UserInfo userInfo, String userId);
UserInfo getUserInfoByUserId(String userId);
PaginationResultVO findListByPage(UserInfoQuery userInfoQuery);
Integer findCountByParam(UserInfoQuery param);
List<UserInfo> findListByParam(UserInfoQuery param);
void updateUserStatus(String userId, Integer status);
void changeUserSpace(String userId, Integer changeSpace);
}
@@ -0,0 +1,131 @@
package com.easypan.service.impl;
import com.easypan.utils.RedisComponent;
import com.easypan.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SysSettingsDto;
import com.easypan.entity.po.EmailCode;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.query.EmailCodeQuery;
import com.easypan.entity.query.UserInfoQuery;
import com.easypan.exception.BusinessException;
import com.easypan.mappers.EmailCodeMapper;
import com.easypan.mappers.UserInfoMapper;
import com.easypan.service.EmailCodeService;
import com.easypan.utils.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.util.Date;
/**
* 邮箱验证码 业务接口实现
*/
@Service
public class EmailCodeServiceImpl implements EmailCodeService {
private static final Logger logger = LoggerFactory.getLogger(EmailCodeServiceImpl.class);
@Resource
private JavaMailSender javaMailSender;
@Resource
private EmailCodeMapper<EmailCode, EmailCodeQuery> emailCodeMapper;
@Resource
private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
@Resource
private AppConfig appConfig;
@Resource
private RedisComponent redisComponent;
/**
* 真正发送邮件验证码
* @param toEmail 发送到德邮箱
* @param code 需要发送的验证码
*/
private void sendEmailCode(String toEmail, String code) {
try {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
//邮件发件人
helper.setFrom(appConfig.getSendUserName());
//邮件收件人 1或多个
helper.setTo(toEmail);
SysSettingsDto sysSettingsDto = redisComponent.getSysSettingsDto();
//邮件主题
helper.setSubject(sysSettingsDto.getRegisterEmailTitle());
//邮件内容
helper.setText(String.format(sysSettingsDto.getRegisterEmailContent(), code));
//邮件发送时间
helper.setSentDate(new Date());
//发送
javaMailSender.send(message);
} catch (Exception e) {
logger.error("邮件发送失败", e);
throw new BusinessException("邮件发送失败");
}
}
/**
* 发送邮箱验证码的前置和后置工作
* @param toEmail 发送的邮箱地址
* @param type 0:注册 1:找回密码
*/
@Override
@Transactional
public void sendEmailCode(String toEmail, Integer type) {
//如果是注册,校验邮箱是否已存在
if (type == Constants.REGISTER_ZERO) {
UserInfo userInfo = userInfoMapper.selectByEmail(toEmail);
if (null != userInfo) {
throw new BusinessException("邮箱已经存在");
}
}
String code = StringTools.getRandomNumber(Constants.LENGTH_5);
sendEmailCode(toEmail, code);
// 数据库中的其他验证码置于不可用
emailCodeMapper.disableEmailCode(toEmail);
// 封装EmailCode对象
EmailCode emailCode = new EmailCode();
emailCode.setCode(code);
emailCode.setEmail(toEmail);
emailCode.setStatus(Constants.REGISTER_ZERO);
emailCode.setCreateTime(new Date());
// 插入数据库
emailCodeMapper.insert(emailCode);
}
@Override
public void checkCode(String email, String code) {
EmailCode emailCode = emailCodeMapper.selectByEmailAndCode(email, code);
// 如果没查到数据
if (emailCode == null) {
throw new BusinessException("邮箱验证码不正确");
}
// 如果已经失效或超时
if (emailCode.getStatus() == 1 || System.currentTimeMillis() - emailCode.getCreateTime()
.getTime() > Constants.LENGTH_15 * 1000 * 60) {
throw new BusinessException("邮箱验证已失效");
}
emailCodeMapper.disableEmailCode(email);
}
}
@@ -0,0 +1,829 @@
package com.easypan.service.impl;
import com.easypan.utils.RedisComponent;
import com.easypan.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.dto.UploadResultDto;
import com.easypan.entity.dto.UserSpaceDto;
import com.easypan.entity.enums.*;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.query.SimplePage;
import com.easypan.entity.query.UserInfoQuery;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.exception.BusinessException;
import com.easypan.mappers.FileInfoMapper;
import com.easypan.mappers.UserInfoMapper;
import com.easypan.service.FileInfoService;
import com.easypan.utils.DateUtil;
import com.easypan.utils.ProcessUtils;
import com.easypan.utils.ScaleFilter;
import com.easypan.utils.StringTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 文件信息 业务接口实现
*/
@Service
@Slf4j
public class FileInfoServiceImpl implements FileInfoService {
@Resource
private FileInfoMapper<FileInfo, FileInfoQuery> fileInfoMapper;
@Resource
private RedisComponent redisComponent;
@Resource
private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
@Resource
private AppConfig appConfig;
@Resource
@Lazy
private FileInfoServiceImpl fileInfoService;
@Override
public FileInfo getFileInfoByFileIdAndUserId(String fileId, String userId) {
return fileInfoMapper.selectByFileIdAndUserId(fileId, userId);
}
/**
* 创建文件夹
*/
@Override
// @Transactional
public FileInfo newFolder(String filePid, String userId, String folderName) {
// 检查是否还有同名文件夹
checkFileName(filePid, userId, folderName, FileFolderTypeEnums.FOLDER.getType());
Date curDate = new Date();
FileInfo fileInfo = new FileInfo();
fileInfo.setFileId(StringTools.getRandomString(Constants.LENGTH_10));
fileInfo.setUserId(userId);
fileInfo.setFilePid(filePid);
fileInfo.setFileName(folderName);
fileInfo.setFolderType(FileFolderTypeEnums.FOLDER.getType());
fileInfo.setCreateTime(curDate);
fileInfo.setLastUpdateTime(curDate);
fileInfo.setStatus(FileStatusEnums.USING.getStatus());
fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());
fileInfoMapper.insert(fileInfo);
return fileInfo;
}
@Override
public List<FileInfo> findListByParam(FileInfoQuery param) {
return fileInfoMapper.selectList(param);
}
@Override
public List<FileInfo> loadAllFolder(String userId, String filePid, String currentFileIds) {
FileInfoQuery query = new FileInfoQuery();
query.setUserId(userId);
query.setFilePid(filePid);
query.setFolderType(FileFolderTypeEnums.FOLDER.getType());
if (!StringTools.isEmpty(currentFileIds)) {
query.setExcludeFileIdArray(currentFileIds.split(","));
}
query.setDelFlag(FileDelFlagEnums.USING.getFlag());
query.setOrderBy("create_time desc");
return fileInfoService.findListByParam(query);
}
// 移动文件到指定文件夹
@Override
public void changeFileFolder(String fileIds, String filePid, String userId) {
if (fileIds.equals(filePid)) {
//移动到自己
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
// 以filePid当做fileId加上userId查询
if (!Constants.ZERO_STR.equals(filePid)) {
FileInfo fileInfo = getFileInfoByFileIdAndUserId(filePid, userId);
// 当前用户移动到的目录不存在或者不是目录
if (fileInfo == null || !FileDelFlagEnums.USING.getFlag().equals(fileInfo.getDelFlag())) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
}
// fileIds -> {fileId1,fileId2,fileId3...}
String[] fileIdArray = fileIds.split(",");
// 如果移动到的目录正常,查询出toFile下的所有文件
FileInfoQuery query = new FileInfoQuery();
query.setFilePid(filePid);
query.setUserId(userId);
List<FileInfo> dbFileList = findListByParam(query);
// 将查询出的list集合收集为以fileName为key, 以集合元素fileInfo为值
// (file1, file2) -> file2) 如果两个文件名字相同,取第二个
Map<String, FileInfo> dbFileNameMap = dbFileList.stream()
.collect(Collectors.toMap(FileInfo::getFileName,
Function.identity(),
(file1, file2) -> file2));
//查询选中的文件
query = new FileInfoQuery();
query.setUserId(userId);
query.setFileIdArray(fileIdArray);
List<FileInfo> selectFileList = findListByParam(query);
//如果存在名字相同,则将所选文件重命名
for (FileInfo item : selectFileList) {
FileInfo rootFileInfo = dbFileNameMap.get(item.getFileName());
FileInfo updateInfo = new FileInfo();
if (rootFileInfo != null) {
//文件名已经存在,重命名被还原的文件名
String fileName = StringTools.rename(item.getFileName());
updateInfo.setFileName(fileName);
}
updateInfo.setFilePid(filePid);
fileInfoMapper.updateByFileIdAndUserId(updateInfo, item.getFileId(), userId);
}
}
private List<FileInfo> selectListByIdsAndDelFlag(String userId, String fileIds, Integer delFlag) {
String[] fileIdArray = fileIds.split(",");
FileInfoQuery query = new FileInfoQuery();
query.setUserId(userId);
query.setFileIdArray(fileIdArray);
query.setDelFlag(delFlag);
return fileInfoMapper.selectList(query);
}
// 批量将文件放入回收站
@Override
@Transactional
public void removeFile2RecycleBatch(String userId, String fileIds) {
// 查询该用户需删除的fileIds并且状态为使用中的文件
List<FileInfo> fileInfoList = selectListByIdsAndDelFlag(userId, fileIds, FileDelFlagEnums.USING.getFlag());
if (fileInfoList.isEmpty()) {
return;
}
// 如果不为空
List<String> delFilePidList = new ArrayList<>();
fileInfoList.stream()
.filter(fileInfo ->
fileInfo.getFolderType().equals(FileFolderTypeEnums.FOLDER.getType()))
.forEach(fileInfo ->
findAllSubFolderFileIdList(delFilePidList, userId, fileInfo.getFileId(), FileDelFlagEnums.USING.getFlag()));
//将目录下的所有文件更新为已删除
if (!delFilePidList.isEmpty()) {
FileInfo updateInfo = new FileInfo();
updateInfo.setDelFlag(FileDelFlagEnums.DEL.getFlag());
this.fileInfoMapper.updateFileDelFlagBatch(updateInfo, userId, delFilePidList,
null, FileDelFlagEnums.USING.getFlag());
}
//将选中的文件更新为回收站
List<String> delFileIdList = Arrays.asList(fileIds.split(","));
FileInfo fileInfo = new FileInfo();
fileInfo.setRecoveryTime(new Date());
fileInfo.setDelFlag(FileDelFlagEnums.RECYCLE.getFlag());
this.fileInfoMapper.updateFileDelFlagBatch(fileInfo, userId, null,
delFileIdList, FileDelFlagEnums.USING.getFlag());
}
// 回收站还原
@Override
@Transactional
public void recoverFileBatch(String userId, String fileIds) {
// 首先将选中的需还原的文件查找出来
List<FileInfo> fileInfoList = selectListByIdsAndDelFlag(userId, fileIds, FileDelFlagEnums.RECYCLE.getFlag());
//delFileSubFolderFileIdList为所有文件夹的id
List<String> delFileSubFolderFileIdList = new ArrayList<>();
//找到所选文件子目录文件ID
// 如果是文件夹,递归找出该文件夹中的所有文件夹
fileInfoList.stream()
.filter(fileInfo ->
fileInfo.getFolderType().equals(FileFolderTypeEnums.FOLDER.getType()))
.forEach(fileInfo ->
findAllSubFolderFileIdList(delFileSubFolderFileIdList, userId,
fileInfo.getFileId(), FileDelFlagEnums.USING.getFlag()));
// 查询所有跟目录的文件准备判断是否需要重命名
FileInfoQuery query = new FileInfoQuery();
query = new FileInfoQuery();
query.setUserId(userId);
query.setDelFlag(FileDelFlagEnums.USING.getFlag());
query.setFilePid(Constants.ZERO_STR);
List<FileInfo> allRootFileList = this.fileInfoMapper.selectList(query);
Map<String, FileInfo> rootFileMap =
allRootFileList.stream().
collect(Collectors.toMap(FileInfo::getFileName, Function.identity(), (file1, file2) -> file2));
// 将目录下的所有删除的文件更新为正常
if (!delFileSubFolderFileIdList.isEmpty()) {
FileInfo fileInfo = new FileInfo();
fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());
this.fileInfoMapper.updateFileDelFlagBatch(fileInfo, userId, delFileSubFolderFileIdList,
null, FileDelFlagEnums.DEL.getFlag());
}
// 将选中的文件更新为正常,且父级目录到跟目录
List<String> delFileIdList = Arrays.asList(fileIds.split(","));
FileInfo fileInfo = new FileInfo();
fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());
fileInfo.setFilePid(Constants.ZERO_STR);
fileInfo.setLastUpdateTime(new Date());
this.fileInfoMapper.updateFileDelFlagBatch(fileInfo, userId, null, delFileIdList,
FileDelFlagEnums.RECYCLE.getFlag());
//将所选文件重命名
for (FileInfo item : fileInfoList) {
// 从map中查找名字相同的文件
FileInfo rootFileInfo = rootFileMap.get(item.getFileName());
//文件名已经存在,重命名被还原的文件名
if (rootFileInfo != null) {
String fileName = StringTools.rename(item.getFileName());
FileInfo updateInfo = new FileInfo();
updateInfo.setFileName(fileName);
this.fileInfoMapper.updateByFileIdAndUserId(updateInfo, item.getFileId(), userId);
}
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delFileBatch(String userId, String fileIds, boolean adminOp) {
List<FileInfo> fileInfoList = selectListByIdsAndDelFlag(userId, fileIds, FileDelFlagEnums.RECYCLE.getFlag());
List<String> delFileSubFolderFileIdList = new ArrayList<>();
//找到所选文件子目录文件ID
fileInfoList.stream()
.filter(fileInfo ->
fileInfo.getFolderType().equals(FileFolderTypeEnums.FOLDER.getType()))
.forEach(fileInfo ->
findAllSubFolderFileIdList(delFileSubFolderFileIdList, userId,
fileInfo.getFileId(), FileDelFlagEnums.DEL.getFlag()));
//删除所选文件,子目录中的文件
if (!delFileSubFolderFileIdList.isEmpty()) {
this.fileInfoMapper.delFileBatch(userId, delFileSubFolderFileIdList, null, adminOp
? null : FileDelFlagEnums.DEL.getFlag());
}
//删除所选文件
this.fileInfoMapper.delFileBatch(userId, null, Arrays.asList(fileIds.split(",")),
adminOp ? null : FileDelFlagEnums.RECYCLE.getFlag());
Long useSpace = this.fileInfoMapper.selectUseSpace(userId);
UserInfo userInfo = new UserInfo();
userInfo.setUseSpace(useSpace);
userInfoMapper.updateByUserId(userInfo, userId);
//设置缓存
UserSpaceDto userSpaceDto = redisComponent.getUserSpaceUse(userId);
userSpaceDto.setUseSpace(useSpace);
redisComponent.saveUserSpaceUse(userId, userSpaceDto);
}
@Override
public void saveShare(String shareRootFilePid, String shareFileIds, String myFolderId,
String shareUserId, String currentUserId) {
String[] shareFileIdArray = shareFileIds.split(",");
//目标目录文件列表
FileInfoQuery fileInfoQuery = new FileInfoQuery();
fileInfoQuery.setUserId(currentUserId);
fileInfoQuery.setFilePid(myFolderId);
// 目标文件夹下所有文件
List<FileInfo> currentFileList = this.fileInfoMapper.selectList(fileInfoQuery);
// 映射成map
Map<String, FileInfo> currentFileMap =
currentFileList.stream()
.collect(Collectors.toMap(FileInfo::getFileName, Function.identity(), (file1, file2) -> file2));
//选择的文件
fileInfoQuery = new FileInfoQuery();
fileInfoQuery.setUserId(shareUserId);
fileInfoQuery.setFileIdArray(shareFileIdArray);
// 选中的所有文件
List<FileInfo> shareFileList = this.fileInfoMapper.selectList(fileInfoQuery);
//重命名选择的文件
List<FileInfo> copyFileList = new ArrayList<>();
Date curDate = new Date();
for (FileInfo item : shareFileList) {
FileInfo haveFile = currentFileMap.get(item.getFileName());
if (haveFile != null) {
item.setFileName(StringTools.rename(item.getFileName()));
}
// 需要找出所有文件复制
findAllSubFile(copyFileList, item, shareUserId, currentUserId, curDate, myFolderId);
}
// System.out.println(copyFileList.size());
this.fileInfoMapper.insertBatch(copyFileList);
}
@Override
public void deleteFileByUserId(String userId) {
this.fileInfoMapper.deleteFileByUserId(userId);
}
private void findAllSubFile(List<FileInfo> copyFileList, FileInfo fileInfo, String sourceUserId,
String currentUserId, Date curDate, String newFilePid) {
// 将文件添加进集合
String sourceFileId = fileInfo.getFileId();
fileInfo.setCreateTime(curDate);
fileInfo.setLastUpdateTime(curDate);
fileInfo.setFilePid(newFilePid);
fileInfo.setUserId(currentUserId);
String newFileId = StringTools.getRandomString(Constants.LENGTH_10);
fileInfo.setFileId(newFileId);
copyFileList.add(fileInfo);
// 如果是目录的话,递归添加
if (FileFolderTypeEnums.FOLDER.getType().equals(fileInfo.getFolderType())) {
FileInfoQuery query = new FileInfoQuery();
query.setFilePid(sourceFileId);
query.setUserId(sourceUserId);
List<FileInfo> sourceFileList = this.fileInfoMapper.selectList(query);
sourceFileList.forEach(item -> findAllSubFile(copyFileList, item, sourceUserId, currentUserId, curDate, newFileId));
}
}
//
// /**
// * 前端传参: String shareId, String filePid
// * shareId -> shareSessionDto
// * @param rootFilePid shareSessionDto.getFileId()
// * @param userId shareSessionDto.getShareUserId()
// * @param fileId filePid
// */
// @Override
// public void checkRootFilePid(String rootFilePid, String userId, String fileId) {
// if (StringTools.isEmpty(fileId)) {
// throw new BusinessException(ResponseCodeEnum.CODE_600);
// }
// if (rootFilePid.equals(fileId)) {
// return;
// }
// checkFilePid(rootFilePid, fileId, userId);
// }
// private void checkFilePid(String rootFilePid, String fileId, String userId) {
// FileInfo fileInfo = this.fileInfoMapper.selectByFileIdAndUserId(fileId, userId);
// if (fileInfo == null) {
// throw new BusinessException(ResponseCodeEnum.CODE_600);
// }
// if (Constants.ZERO_STR.equals(fileInfo.getFilePid())) {
// throw new BusinessException(ResponseCodeEnum.CODE_600);
// }
// if (fileInfo.getFilePid().equals(rootFilePid)) {
// return;
// }
// checkFilePid(rootFilePid, fileInfo.getFilePid(), userId);
// }
// 递归查找文件夹下的所有文件
private void findAllSubFolderFileIdList(List<String> fileIdList, String userId, String fileId, Integer delFlag) {
// 首先将自己添加进删除集合
fileIdList.add(fileId);
// 然后查找自己下面的所有的文件夹
FileInfoQuery query = new FileInfoQuery();
query.setUserId(userId);
query.setFilePid(fileId);
query.setDelFlag(delFlag);
query.setFolderType(FileFolderTypeEnums.FOLDER.getType());
List<FileInfo> fileInfoList = this.fileInfoMapper.selectList(query);
for (FileInfo fileInfo : fileInfoList) {
findAllSubFolderFileIdList(fileIdList, userId, fileInfo.getFileId(), delFlag);
}
}
private void checkFileName(String filePid, String userId,
String fileName, Integer folderType) {
FileInfoQuery fileInfoQuery = new FileInfoQuery();
fileInfoQuery.setFolderType(folderType);
fileInfoQuery.setFileName(fileName);
fileInfoQuery.setFilePid(filePid);
fileInfoQuery.setUserId(userId);
fileInfoQuery.setDelFlag(FileDelFlagEnums.USING.getFlag());
Integer count = this.fileInfoMapper.selectCount(fileInfoQuery);
if (count > 0) {
throw new BusinessException("此目录下已存在同名文件,请修改名称");
}
}
@Override
public FileInfo rename(String fileId, String userId, String fileName) {
FileInfo fileInfo = this.fileInfoMapper.selectByFileIdAndUserId(fileId, userId);
if (fileInfo == null) {
throw new BusinessException("文件不存在");
}
String filePid = fileInfo.getFilePid();
checkFileName(filePid, userId, fileName, fileInfo.getFolderType());
//文件获取后缀
if (FileFolderTypeEnums.FILE.getType().equals(fileInfo.getFolderType())) {
fileName = fileName + StringTools.getFileSuffix(fileInfo.getFileName());
}
Date curDate = new Date();
FileInfo dbInfo = new FileInfo();
dbInfo.setFileName(fileName);
dbInfo.setLastUpdateTime(curDate);
fileInfoMapper.updateByFileIdAndUserId(dbInfo, fileId, userId);
fileInfo.setFileName(fileName);
fileInfo.setLastUpdateTime(curDate);
return fileInfo;
}
/**
* 分页查询方法
*/
@Override
public PaginationResultVO<FileInfo> findListByPage(FileInfoQuery param) {
// 记录条数
int count = fileInfoMapper.selectCount(param);
// 如果未选择页面大小则使用默认的15
int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();
/**
* param.getPageNo() 第几页
* count 共多少条记录
* pageSize 一页显示多少页
*/
SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
param.setSimplePage(page);
List<FileInfo> list = fileInfoMapper.selectList(param);
PaginationResultVO<FileInfo> result = new PaginationResultVO(count,
page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
return result;
}
/**
* 实现上传核心方法 uploadFile -> transferFile -> union -> 生成缩略图
*
* @param webUserDto 用户信息
* @param fileId 非必传,第一个分片文件不传
* @param file 传的文件
* @param fileName 文件名
* @param filePid 在哪一个目录
* @param fileMd5 前端做的
* @param chunkIndex 第几个分片
* @param chunks 总共有多少个分片
*/
@Override
@Transactional
public UploadResultDto uploadFile(SessionWebUserDto webUserDto, String fileId, MultipartFile file,
String fileName, String filePid, String fileMd5, Integer chunkIndex, Integer chunks) {
UploadResultDto uploadResultDto = new UploadResultDto();
boolean uploadSuccess = true;
File tempFileFolder = null;
Date curDate = new Date();
try {
if (StringTools.isEmpty(fileId)) {
fileId = StringTools.getRandomString(Constants.LENGTH_10);
}
uploadResultDto.setFileId(fileId);
// 获取用户可用空间
String userId = webUserDto.getUserId();
UserSpaceDto userSpaceDto = redisComponent.getUserSpaceUse(userId);
// 第一个文件,判断是否可秒传
if (chunkIndex == 0) {
// 封装查询条件
FileInfoQuery fileInfoQuery = new FileInfoQuery();
// 文件MD5值
fileInfoQuery.setFileMd5(fileMd5);
// 只取第一条
fileInfoQuery.setSimplePage(new SimplePage(0, 1));
// 转码成功,使用中
fileInfoQuery.setStatus(FileStatusEnums.USING.getStatus());
// 查询
List<FileInfo> dbFileList = fileInfoMapper.selectList(fileInfoQuery);
if (!dbFileList.isEmpty()) {
// 数据库中找到,可秒传
FileInfo dbFile = dbFileList.get(0);
// 判断文件大小
if (dbFile.getFileSize() + userSpaceDto.getUseSpace() > userSpaceDto.getTotalSpace()) {
// 空间不足
throw new BusinessException(ResponseCodeEnum.CODE_904);
}
dbFile.setFileId(fileId);
dbFile.setFilePid(filePid);
dbFile.setUserId(userId);
dbFile.setCreateTime(curDate);
dbFile.setLastUpdateTime(curDate);
dbFile.setStatus(FileStatusEnums.USING.getStatus());
dbFile.setDelFlag(FileDelFlagEnums.USING.getFlag());
dbFile.setFileMd5(fileMd5);
// 文件自动重命名
fileName = autoRename(filePid, userId, fileName);
dbFile.setFileName(fileName);
// 更新数据库中的文件信息
fileInfoMapper.insert(dbFile);
uploadResultDto.setStatus(UploadStatusEnums.UPLOAD_SECONDS.getCode());
// 更新用户使用空间
updateUserSpace(webUserDto, dbFile.getFileSize());
return uploadResultDto;
}
}
// 判断磁盘空间(分片 + 临时 + 已使用 > 总 ? 抛异常 : 继续)
Long currentTempSize = redisComponent.getFileTempSize(userId, fileId);
if (file.getSize() + currentTempSize + userSpaceDto.getUseSpace() >
userSpaceDto.getTotalSpace()) {
//空间不足
throw new BusinessException(ResponseCodeEnum.CODE_904);
}
// 暂存临时目录 e:/webser/web_app/easypan/temp/
String tempFolderName = appConfig.getProjectFolder() + Constants.FILE_FOLDER_TEMP;
// userId + fileId
String currentUserFolderName = webUserDto.getUserId() + fileId;
// e:/webser/web_app/easypan/temp/{userId}/{fileId}
tempFileFolder = new File(tempFolderName + "/" + currentUserFolderName);
if (!tempFileFolder.exists()) {
tempFileFolder.mkdirs();
}
File newFile = new File(tempFileFolder.getPath() + "/" + chunkIndex);
file.transferTo(newFile);
redisComponent.saveFileTempSize(userId, fileId, file.getSize());
if (chunkIndex < chunks - 1) {
uploadResultDto.setStatus(UploadStatusEnums.UPLOADING.getCode());
return uploadResultDto;
}
// 如果是最后一个分片,上传完成,记录数据库,异步合并分片
String month = DateUtil.format(new Date(), DateTimePatternEnum.YYYYMM.getPattern());
String fileSuffix = StringTools.getFileSuffix(fileName);
// 真实文件名
// userId + fileId.fileSuffix
String realFileName = currentUserFolderName + fileSuffix;
// 根据后缀从枚举类中获取文件类别
FileTypeEnums fileTypeEnums = FileTypeEnums.getFileTypeBySuffix(fileSuffix);
//自动重命名
fileName = autoRename(filePid, userId, fileName);
FileInfo fileInfo = new FileInfo();
fileInfo.setFileId(fileId);
fileInfo.setUserId(userId);
fileInfo.setFileMd5(fileMd5);
fileInfo.setFileName(fileName);
fileInfo.setFilePath(month + "/" + realFileName);
fileInfo.setFilePid(filePid);
fileInfo.setCreateTime(curDate);
fileInfo.setLastUpdateTime(curDate);
fileInfo.setFileCategory(fileTypeEnums.getCategory().getCategory());
fileInfo.setFileType(fileTypeEnums.getType());
fileInfo.setStatus(FileStatusEnums.TRANSFER.getStatus());
fileInfo.setFolderType(FileFolderTypeEnums.FILE.getType());
fileInfo.setDelFlag(FileDelFlagEnums.USING.getFlag());
this.fileInfoMapper.insert(fileInfo);
Long totalSize = redisComponent.getFileTempSize(webUserDto.getUserId(), fileId);
updateUserSpace(webUserDto, totalSize);
uploadResultDto.setStatus(UploadStatusEnums.UPLOAD_FINISH.getCode());
// 事务提交后执行
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
fileInfoService.transferFile(fileInfo.getFileId(), webUserDto);
redisComponent.removeFileTempSize(userId, fileInfo.getFileId());
}
});
} catch (BusinessException e) {
log.error("文件上传失败");
uploadSuccess = false;
throw e;
} catch (Exception e) {
log.error("文件上传失败");
uploadSuccess = false;
} finally {
//如果上传失败,清除临时目录
if (tempFileFolder != null && !uploadSuccess) {
try {
FileUtils.deleteDirectory(tempFileFolder);
} catch (IOException e) {
log.error("删除临时目录失败");
}
}
}
return uploadResultDto;
}
// 转码
@Async
public void transferFile(String fileId, SessionWebUserDto webUserDto) {
boolean transferSuccess = true;
String targetFilePath = null;
String cover = null;
FileTypeEnums fileTypeEnum = null;
FileInfo fileInfo = fileInfoMapper.selectByFileIdAndUserId(fileId, webUserDto.getUserId());
try {
if (fileInfo == null || !FileStatusEnums.TRANSFER.getStatus().equals(fileInfo.getStatus())) {
return;
}
//临时目录
String tempFolderName = appConfig.getProjectFolder() + Constants.FILE_FOLDER_TEMP;
String currentUserFolderName = webUserDto.getUserId() + fileId;
File fileFolder = new File(tempFolderName + "/" + currentUserFolderName);
if (!fileFolder.exists()) {
fileFolder.mkdirs();
}
//文件后缀
String fileSuffix = StringTools.getFileSuffix(fileInfo.getFileName());
String month = DateUtil.format(fileInfo.getCreateTime(), DateTimePatternEnum.YYYYMM.getPattern());
//目标目录 e:/webser/web_app/easypan + /file + /{month}
String targetFolderName = appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE;
File targetFolder = new File(targetFolderName + "/" + month);
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
//真实文件名 {userId+fileId}
String realFileName = currentUserFolderName + fileSuffix;
//真实文件路径
targetFilePath = targetFolder.getPath() + "/" + realFileName;
//合并文件
/**
* fileFolder.getPath() 临时目录
* targetFilePath 目标目录
* fileInfo.getFileName() 文件名
* delSource
*/
union(fileFolder.getPath(), targetFilePath, fileInfo.getFileName(), true);
fileTypeEnum = FileTypeEnums.getFileTypeBySuffix(fileSuffix);
if (FileTypeEnums.VIDEO == fileTypeEnum) {
//视频文件切割
cutFile4Video(fileId, targetFilePath);
//视频生成缩略图
cover = month + "/" + currentUserFolderName + Constants.IMAGE_PNG_SUFFIX;
String coverPath = targetFolderName + "/" + cover;
ScaleFilter.createCover4Video(new File(targetFilePath), Constants.LENGTH_150, new File(coverPath));
} else if (FileTypeEnums.IMAGE == fileTypeEnum) {
//生成缩略图
cover = month + "/" + realFileName.replace(".", "_.");
String coverPath = targetFolderName + "/" + cover;
Boolean created = ScaleFilter.createThumbnailWidthFFmpeg(new File(targetFilePath), Constants.LENGTH_150, new File(coverPath), false);
// 如果没有生成缩略图,直接将原图复制当做缩略图
if (!created) {
FileUtils.copyFile(new File(targetFilePath), new File(coverPath));
}
}
} catch (Exception e) {
log.error("文件转码失败,文件Id:{},userId:{}", fileId, webUserDto.getUserId(), e);
transferSuccess = false;
} finally {
FileInfo updateInfo = new FileInfo();
updateInfo.setFileSize(new File(targetFilePath).length());
updateInfo.setFileCover(cover);
updateInfo.setStatus(transferSuccess ? FileStatusEnums.USING.getStatus() : FileStatusEnums.TRANSFER_FAIL.getStatus());
fileInfoMapper.updateFileStatusWithOldStatus(fileId, webUserDto.getUserId(), updateInfo, FileStatusEnums.TRANSFER.getStatus());
}
}
public static void union(String dirPath, String toFilePath, String fileName, boolean delSource)
throws BusinessException {
// 目录不存在,直接抛异常
File dir = new File(dirPath);
if (!dir.exists()) {
throw new BusinessException("目录不存在");
}
// 取出temp目录下的所有文件
File[] fileList = dir.listFiles();
File targetFile = new File(toFilePath);
// RandomAccessFile支持"随机访问"的方式,程序可以直接跳转到文件的任意地方来读写数据。
RandomAccessFile writeFile = null;
try {
// 目标目录
writeFile = new RandomAccessFile(targetFile, "rw");
byte[] b = new byte[1024 * 10];
for (int i = 0; i < fileList.length; i++) {
int len = -1;
//创建读块文件的对象,分别取出 0, 1, 2 ...
File chunkFile = new File(dirPath + File.separator + i);
RandomAccessFile readFile = null;
try {
readFile = new RandomAccessFile(chunkFile, "r");
while ((len = readFile.read(b)) != -1) {
writeFile.write(b, 0, len);
}
} catch (Exception e) {
log.error("合并分片失败", e);
throw new BusinessException("合并文件失败");
} finally {
if (readFile != null) {
readFile.close();
}
}
}
} catch (Exception e) {
log.error("合并文件:{}失败", fileName, e);
throw new BusinessException("合并文件" + fileName + "出错了");
} finally {
try {
if (writeFile != null) {
writeFile.close();
}
} catch (IOException e) {
log.error("关闭流失败", e);
}
if (delSource) {
if (dir.exists()) {
try {
// 以递归方式删除目录。
FileUtils.deleteDirectory(dir);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
// 利用java代码操作命令行窗口执行FFmpeg对视频进行切割,生成.m3u8索引文件和.ts切片文件
private void cutFile4Video(String fileId, String videoFilePath) {
//创建同名切片目录
File tsFolder = new File(videoFilePath.substring(0, videoFilePath.lastIndexOf(".")));
if (!tsFolder.exists()) {
tsFolder.mkdirs();
}
final String CMD_TRANSFER_2TS = "ffmpeg -y -i %s -vcodec copy -acodec copy -vbsf h264_mp4toannexb %s";
final String CMD_CUT_TS = "ffmpeg -i %s -c copy -map 0 -f segment -segment_list %s -segment_time 30 %s/%s_%%4d.ts";
String tsPath = tsFolder + "/" + Constants.TS_NAME;
//生成index.ts
String cmd = String.format(CMD_TRANSFER_2TS, videoFilePath, tsPath);
ProcessUtils.executeCommand(cmd, false);
//生成索引文件.m3u8 和切片.ts
cmd = String.format(CMD_CUT_TS, tsPath, tsFolder.getPath() + "/" + Constants.M3U8_NAME, tsFolder.getPath(), fileId);
ProcessUtils.executeCommand(cmd, false);
//删除index.ts
new File(tsPath).delete();
}
private void updateUserSpace(SessionWebUserDto webUserDto, Long useSpace) {
Integer count = userInfoMapper.updateUserSpace(webUserDto.getUserId(),
useSpace, null);
// 更新失败,使用空间超过总空间
if (count == 0) {
throw new BusinessException(ResponseCodeEnum.CODE_904);
}
// 更新成功,同时更新redis中的缓存
String userId = webUserDto.getUserId();
UserSpaceDto spaceDto = redisComponent.getUserSpaceUse(userId);
spaceDto.setUseSpace(spaceDto.getUseSpace() + useSpace);
redisComponent.saveUserSpaceUse(userId, spaceDto);
}
private String autoRename(String filePid, String userId, String fileName) {
// 封装查询条件,如果查询出数据,则需要重命名
FileInfoQuery fileInfoQuery = new FileInfoQuery();
fileInfoQuery.setUserId(userId);
fileInfoQuery.setFilePid(filePid);
fileInfoQuery.setDelFlag(FileDelFlagEnums.USING.getFlag());
fileInfoQuery.setFileName(fileName);
Integer count = this.fileInfoMapper.selectCount(fileInfoQuery);
if (count > 0) {
return StringTools.rename(fileName);
}
return fileName;
}
}
@@ -0,0 +1,170 @@
package com.easypan.service.impl;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionShareDto;
import com.easypan.entity.enums.PageSize;
import com.easypan.entity.enums.ResponseCodeEnum;
import com.easypan.entity.enums.ShareValidTypeEnums;
import com.easypan.entity.po.FileShare;
import com.easypan.entity.query.FileShareQuery;
import com.easypan.entity.query.SimplePage;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.exception.BusinessException;
import com.easypan.mappers.FileShareMapper;
import com.easypan.service.FileShareService;
import com.easypan.utils.DateUtil;
import com.easypan.utils.StringTools;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* 分享信息 业务接口实现
*/
@Service("fileShareService")
public class FileShareServiceImpl implements FileShareService {
@Resource
private FileShareMapper<FileShare, FileShareQuery> fileShareMapper;
/**
* 根据条件查询列表
*/
@Override
public List<FileShare> findListByParam(FileShareQuery param) {
return this.fileShareMapper.selectList(param);
}
/**
* 根据条件查询列表
*/
@Override
public Integer findCountByParam(FileShareQuery param) {
return this.fileShareMapper.selectCount(param);
}
/**
* 分页查询方法
*/
@Override
public PaginationResultVO<FileShare> findListByPage(FileShareQuery param) {
int count = this.findCountByParam(param);
int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();
SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
param.setSimplePage(page);
List<FileShare> list = this.findListByParam(param);
PaginationResultVO<FileShare> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
return result;
}
/**
* 新增
*/
@Override
public Integer add(FileShare bean) {
return this.fileShareMapper.insert(bean);
}
/**
* 批量新增
*/
@Override
public Integer addBatch(List<FileShare> listBean) {
if (listBean == null || listBean.isEmpty()) {
return 0;
}
return this.fileShareMapper.insertBatch(listBean);
}
/**
* 批量新增或者修改
*/
@Override
public Integer addOrUpdateBatch(List<FileShare> listBean) {
if (listBean == null || listBean.isEmpty()) {
return 0;
}
return this.fileShareMapper.insertOrUpdateBatch(listBean);
}
/**
* 根据ShareId获取对象
*/
@Override
public FileShare getFileShareByShareId(String shareId) {
return this.fileShareMapper.selectByShareId(shareId);
}
/**
* 根据ShareId修改
*/
@Override
public Integer updateFileShareByShareId(FileShare bean, String shareId) {
return this.fileShareMapper.updateByShareId(bean, shareId);
}
/**
* 根据ShareId删除
*/
@Override
public Integer deleteFileShareByShareId(String shareId) {
return this.fileShareMapper.deleteByShareId(shareId);
}
@Override
@Transactional
public void deleteFileShareBatch(String[] shareIdArray, String userId) {
Integer count = fileShareMapper.deleteFileShareBatch(shareIdArray, userId);
if (count != shareIdArray.length) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
}
@Override
public void saveShare(FileShare share) {
ShareValidTypeEnums typeEnum = ShareValidTypeEnums.getByType(share.getValidType());
if (null == typeEnum) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
// 设置过期时间
if (typeEnum != ShareValidTypeEnums.FOREVER) {
share.setExpireTime(DateUtil.getAfterDate(typeEnum.getDays()));
}
Date curDate = new Date();
// 设置分享时间
share.setShareTime(curDate);
if (StringTools.isEmpty(share.getCode())) {
share.setCode(StringTools.getRandomString(Constants.LENGTH_5));
}
share.setShareId(StringTools.getRandomString(Constants.LENGTH_20));
this.fileShareMapper.insert(share);
}
@Override
public SessionShareDto checkShareCode(String shareId, String code) {
FileShare share = this.fileShareMapper.selectByShareId(shareId);
if (null == share || (share.getExpireTime() != null && new Date().after(share.getExpireTime()))) {
throw new BusinessException(ResponseCodeEnum.CODE_902);
}
if (!share.getCode().equals(code)) {
throw new BusinessException("提取码错误");
}
//更新浏览次数
this.fileShareMapper.updateShareShowCount(shareId);
SessionShareDto shareSessionDto = new SessionShareDto();
shareSessionDto.setShareId(shareId);
shareSessionDto.setShareUserId(share.getUserId());
shareSessionDto.setFileId(share.getFileId());
shareSessionDto.setExpireTime(share.getExpireTime());
return shareSessionDto;
}
}
@@ -0,0 +1,202 @@
package com.easypan.service.impl;
import com.easypan.utils.RedisComponent;
import com.easypan.config.AppConfig;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.SessionWebUserDto;
import com.easypan.entity.dto.SysSettingsDto;
import com.easypan.entity.dto.UserSpaceDto;
import com.easypan.entity.enums.PageSize;
import com.easypan.entity.enums.UserStatusEnum;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.query.SimplePage;
import com.easypan.entity.query.UserInfoQuery;
import com.easypan.entity.vo.PaginationResultVO;
import com.easypan.exception.BusinessException;
import com.easypan.mappers.FileInfoMapper;
import com.easypan.mappers.UserInfoMapper;
import com.easypan.service.EmailCodeService;
import com.easypan.service.FileInfoService;
import com.easypan.service.UserInfoService;
import com.easypan.utils.StringTools;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* 用户信息 业务接口实现
*/
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Resource
private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
@Resource
private EmailCodeService emailCodeService;
@Resource
private FileInfoMapper<FileInfo, FileInfoQuery> fileInfoMapper;
@Resource
private RedisComponent redisComponent;
@Resource
private AppConfig appConfig;
@Resource
private FileInfoService fileInfoService;
// 注册
@Override
@Transactional
public void register(String email, String nickName, String password, String emailCode) {
UserInfo userInfo = this.userInfoMapper.selectByEmail(email);
if (null != userInfo) {
throw new BusinessException("邮箱账号已经存在");
}
UserInfo nickNameUser = this.userInfoMapper.selectByNickName(nickName);
if (null != nickNameUser) {
throw new BusinessException("昵称已经存在");
}
//校验邮箱验证码
emailCodeService.checkCode(email, emailCode);
// 获取随机id
String userId = StringTools.getRandomNumber(Constants.LENGTH_10);
// 根据输入的信息封装UserInfo对象
userInfo = new UserInfo();
userInfo.setUserId(userId);
userInfo.setNickName(nickName);
userInfo.setEmail(email);
userInfo.setPassword(StringTools.encodeByMD5(password));
userInfo.setJoinTime(new Date());
userInfo.setStatus(UserStatusEnum.ENABLE.getStatus());
// 从redis中取出系统设置
SysSettingsDto sysSettingsDto = redisComponent.getSysSettingsDto();
// 用户空间
userInfo.setTotalSpace(sysSettingsDto.getUserInitUseSpace() * Constants.MB);
userInfo.setUseSpace(fileInfoMapper.selectUseSpace(userId));
this.userInfoMapper.insert(userInfo);
}
@Override
public SessionWebUserDto login(String email, String password) {
UserInfo userInfo = userInfoMapper.selectByEmail(email);
if (userInfo == null || !userInfo.getPassword().equals(password)) {
throw new BusinessException("账号或者密码错误");
}
// 如果账户被禁用
if (UserStatusEnum.DISABLE.getStatus().equals(userInfo.getStatus())) {
throw new BusinessException("账号已禁用");
}
UserInfo updateInfo = new UserInfo();
updateInfo.setLastLoginTime(new Date());
// 根据id更新用户最后一次操作时间
String userId = userInfo.getUserId();
userInfoMapper.updateByUserId(updateInfo, userId);
SessionWebUserDto sessionWebUserDto = new SessionWebUserDto();
sessionWebUserDto.setNickName(userInfo.getNickName());
sessionWebUserDto.setUserId(userId);
if (ArrayUtils.contains(appConfig.getAdminEmails().split(","), email)) {
sessionWebUserDto.setIsAdmin(true);
} else {
sessionWebUserDto.setIsAdmin(false);
}
// 用户空间
UserSpaceDto userSpaceDto = new UserSpaceDto();
userSpaceDto.setUseSpace(fileInfoMapper.selectUseSpace(userId));
userSpaceDto.setTotalSpace(userInfo.getTotalSpace());
redisComponent.saveUserSpaceUse(userId, userSpaceDto);
return sessionWebUserDto;
}
@Override
@Transactional
public void resetPwd(String email, String password, String emailCode) {
// 判断邮箱账号是否存在
UserInfo userInfo = userInfoMapper.selectByEmail(email);
if (userInfo == null) {
throw new BusinessException("邮箱账号不存在");
}
// 判断邮箱验证码是否正确
emailCodeService.checkCode(email, emailCode);
// 邮箱验证码正确可重置密码
UserInfo updateInfo = new UserInfo();
updateInfo.setPassword(StringTools.encodeByMD5(password));
userInfoMapper.updateByEmail(updateInfo, email);;
}
@Override
public void updateUserInfoByUserId(UserInfo bean, String userId) {
userInfoMapper.updateByUserId(bean, userId);
}
@Override
public UserInfo getUserInfoByUserId(String userId) {
return this.userInfoMapper.selectByUserId(userId);
}
@Override
public PaginationResultVO<UserInfo> findListByPage(UserInfoQuery param) {
int count = this.findCountByParam(param);
int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();
SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
param.setSimplePage(page);
List<UserInfo> list = this.findListByParam(param);
PaginationResultVO<UserInfo> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
return result;
}
@Override
public Integer findCountByParam(UserInfoQuery param) {
return this.userInfoMapper.selectCount(param);
}
@Override
public List<UserInfo> findListByParam(UserInfoQuery param) {
return this.userInfoMapper.selectList(param);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateUserStatus(String userId, Integer status) {
UserInfo userInfo = new UserInfo();
userInfo.setStatus(status);
String email = userInfoMapper.selectByUserId(userId).getEmail();
if (ArrayUtils.contains(appConfig.getAdminEmails().split(","), email)) {
throw new BusinessException("不可更改管理员状态");
}
if (UserStatusEnum.DISABLE.getStatus().equals(status)) {
userInfo.setUseSpace(0L);
fileInfoService.deleteFileByUserId(userId);
}
userInfoMapper.updateByUserId(userInfo, userId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void changeUserSpace(String userId, Integer changeSpace) {
Long space = changeSpace * Constants.MB;
this.userInfoMapper.updateUserSpace(userId, null, space);
redisComponent.resetUserSpaceUse(userId);
}
}
@@ -0,0 +1,42 @@
package com.easypan.task;
import com.easypan.entity.enums.FileDelFlagEnums;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.service.FileInfoService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
*/
@Component
public class FileCleanTask {
@Resource
private FileInfoService fileInfoService;
@Scheduled(fixedDelay = 1000 * 60 * 3)
public void execute() {
FileInfoQuery fileInfoQuery = new FileInfoQuery();
fileInfoQuery.setDelFlag(FileDelFlagEnums.RECYCLE.getFlag());
fileInfoQuery.setQueryExpire(true);
List<FileInfo> fileInfoList = fileInfoService.findListByParam(fileInfoQuery);
// 根据用户id进行分组
Map<String, List<FileInfo>> fileInfoMap = fileInfoList.stream()
.collect(Collectors.groupingBy(FileInfo::getUserId));
for (Map.Entry<String, List<FileInfo>> entry : fileInfoMap.entrySet()) {
List<String> fileIds = entry.getValue().stream().
map(FileInfo::getFileId).collect(Collectors.toList());
fileInfoService.delFileBatch(entry.getKey(), String.join(",", fileIds), false);
}
}
}
@@ -0,0 +1,48 @@
package com.easypan.utils;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* 利用spring提供的BeenUtils工具类实现集合元素映射以及单个对象映射
*/
public class CopyTools {
public static <T, S> List<T> copyList(List<S> list, Class<T> clazz) {
return list.stream().map(s -> {
T t = null;
try {
t = clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
BeanUtils.copyProperties(s, t);
return t;
}).collect(Collectors.toList());
/*List<T> list = new ArrayList<T>();
for (S s : sList) {
T t = null;
try {
t = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
BeanUtils.copyProperties(s, t);
list.add(t);
}
return list;
*/
}
public static <T, S> T copy(S s, Class<T> clazz) {
T t = null;
try {
t = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
BeanUtils.copyProperties(s, t);
return t;
}
}
@@ -0,0 +1,60 @@
package com.easypan.utils;
import com.easypan.entity.enums.DateTimePatternEnum;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DateUtil {
private static final Object lockObj = new Object();
private static Map<String, ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
private static SimpleDateFormat getSdf(final String pattern) {
ThreadLocal<SimpleDateFormat> tl = sdfMap.get(pattern);
if (tl == null) {
synchronized (lockObj) {
tl = sdfMap.get(pattern);
if (tl == null) {
tl = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(pattern);
}
};
sdfMap.put(pattern, tl);
}
}
}
return tl.get();
}
public static String format(Date date, String pattern) {
return getSdf(pattern).format(date);
}
public static Date parse(String dateStr, String pattern) {
try {
return getSdf(pattern).parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return new Date();
}
public static Date getAfterDate(Integer day) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR, day);
return calendar.getTime();
}
public static void main(String[] args) {
System.out.println(format(getAfterDate(1), DateTimePatternEnum.YYYY_MM_DD_HH_MM_SS.getPattern()));
}
}
@@ -0,0 +1,112 @@
package com.easypan.utils;
import com.easypan.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
//java执行cmd命令
@Slf4j
public class ProcessUtils {
public static String executeCommand(String cmd, Boolean outprintLog) throws BusinessException {
if (StringTools.isEmpty(cmd)) {
log.error("--- 指令执行失败,因为要执行的FFmpeg指令为空! ---");
return null;
}
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = Runtime.getRuntime().exec(cmd);
// 执行ffmpeg指令
// 取出输出流和错误流的信息
// 注意:必须要取出ffmpeg在执行命令过程中产生的输出信息,如果不取的话当输出流信息填满jvm存储输出留信息的缓冲区时,线程就回阻塞住
PrintStream errorStream = new PrintStream(process.getErrorStream());
PrintStream inputStream = new PrintStream(process.getInputStream());
errorStream.start();
inputStream.start();
// 等待ffmpeg命令执行完
process.waitFor();
// 获取执行结果字符串
String result = errorStream.stringBuffer.append(inputStream.stringBuffer + "\n").toString();
// 输出执行的命令信息
if (outprintLog) {
log.info("执行命令:{},已执行完毕,执行结果:{}", cmd, result);
} else {
log.info("执行命令:{},已执行完毕", cmd);
}
return result;
} catch (Exception e) {
// logger.error("执行命令失败:{} ", e.getMessage());
e.printStackTrace();
throw new BusinessException("视频转换失败");
} finally {
if (null != process) {
ProcessKiller ffmpegKiller = new ProcessKiller(process);
runtime.addShutdownHook(ffmpegKiller);
}
}
}
/**
* 在程序退出前结束已有的FFmpeg进程
*/
private static class ProcessKiller extends Thread {
private Process process;
public ProcessKiller(Process process) {
this.process = process;
}
@Override
public void run() {
this.process.destroy();
}
}
/**
* 用于取出ffmpeg线程执行过程中产生的各种输出和错误流的信息
*/
static class PrintStream extends Thread {
InputStream inputStream = null;
BufferedReader bufferedReader = null;
StringBuffer stringBuffer = new StringBuffer();
public PrintStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public void run() {
try {
if (null == inputStream) {
return;
}
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
}
} catch (Exception e) {
log.error("读取输入流出错了!错误信息:" + e.getMessage());
} finally {
try {
if (null != bufferedReader) {
bufferedReader.close();
}
if (null != inputStream) {
inputStream.close();
}
} catch (IOException e) {
log.error("调用PrintStream读取输出流后,关闭流时出错!");
}
}
}
}
}
@@ -0,0 +1,123 @@
package com.easypan.utils;
import com.easypan.entity.constants.Constants;
import com.easypan.entity.dto.DownloadFileDto;
import com.easypan.entity.dto.SysSettingsDto;
import com.easypan.entity.dto.UserSpaceDto;
import com.easypan.entity.po.FileInfo;
import com.easypan.entity.po.UserInfo;
import com.easypan.entity.query.FileInfoQuery;
import com.easypan.entity.query.UserInfoQuery;
import com.easypan.mappers.FileInfoMapper;
import com.easypan.mappers.UserInfoMapper;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class RedisComponent {
@Resource
private RedisUtils redisUtils;
@Resource
private FileInfoMapper<FileInfo, FileInfoQuery> fileInfoMapper;
@Resource
private UserInfoMapper<UserInfo, UserInfoQuery> userInfoMapper;
/**
* 获取系统设置
* 如果不存在就新建
*/
public SysSettingsDto getSysSettingsDto() {
SysSettingsDto sysSettingsDto = (SysSettingsDto) redisUtils.get(Constants.REDIS_KEY_SYS_SETTING);
if (sysSettingsDto == null) {
sysSettingsDto = new SysSettingsDto();
saveSysSettingsDto(sysSettingsDto);
}
return sysSettingsDto;
}
/**
* 保存设置
*
* @param sysSettingsDto
*/
public void saveSysSettingsDto(SysSettingsDto sysSettingsDto) {
redisUtils.set(Constants.REDIS_KEY_SYS_SETTING, sysSettingsDto);
}
/**
* 保存已使用的空间
*
* @param userId
*/
public void saveUserSpaceUse(String userId, UserSpaceDto userSpaceDto) {
redisUtils.setex(Constants.REDIS_KEY_USER_SPACE_USE + userId,
userSpaceDto, Constants.REDIS_KEY_EXPIRES_DAY);
}
/**
* 获取用户使用的空间
*/
public UserSpaceDto getUserSpaceUse(String userId) {
UserSpaceDto spaceDto = (UserSpaceDto) redisUtils.get(Constants.REDIS_KEY_USER_SPACE_USE + userId);
if (null == spaceDto) {
spaceDto = new UserSpaceDto();
Long useSpace = this.fileInfoMapper.selectUseSpace(userId);
spaceDto.setUseSpace(useSpace);
spaceDto.setTotalSpace(getSysSettingsDto().getUserInitUseSpace() * Constants.MB);
redisUtils.setex(Constants.REDIS_KEY_USER_SPACE_USE + userId, spaceDto, Constants.REDIS_KEY_EXPIRES_DAY);
}
return spaceDto;
}
//保存文件临时大小
public void saveFileTempSize(String userId, String fileId, Long fileSize) {
Long currentSize = getFileTempSize(userId, fileId);
redisUtils.setex(Constants.REDIS_KEY_USER_FILE_TEMP_SIZE + userId + fileId,
currentSize + fileSize, Constants.REDIS_KEY_EXPIRES_ONE_HOUR);
}
public void removeFileTempSize(String userId, String fileId) {
redisUtils.delete(Constants.REDIS_KEY_USER_FILE_TEMP_SIZE + userId + fileId);
}
public Long getFileTempSize(String userId, String fileId) {
// Long currentSize = getFileSizeFromRedis(Constants.REDIS_KEY_USER_FILE_TEMP_SIZE + userId + fileId);
// return currentSize;
String key = Constants.REDIS_KEY_USER_FILE_TEMP_SIZE + userId + fileId;
Object sizeObj = redisUtils.get(key);
if (sizeObj == null) {
return 0L;
}
if (sizeObj instanceof Integer) {
return ((Integer) sizeObj).longValue();
} else if (sizeObj instanceof Long) {
return (Long) sizeObj;
}
return 0L;
}
public void saveDownloadCode(String code, DownloadFileDto downloadFileDto) {
redisUtils.setex(Constants.REDIS_KEY_DOWNLOAD + code,
downloadFileDto, Constants.REDIS_KEY_EXPIRES_FIVE_MIN);
}
public DownloadFileDto getDownloadCode(String code) {
return (DownloadFileDto) redisUtils.get(Constants.REDIS_KEY_DOWNLOAD + code);
}
public UserSpaceDto resetUserSpaceUse(String userId) {
UserSpaceDto spaceDto = new UserSpaceDto();
Long useSpace = this.fileInfoMapper.selectUseSpace(userId);
spaceDto.setUseSpace(useSpace);
UserInfo userInfo = this.userInfoMapper.selectByUserId(userId);
spaceDto.setTotalSpace(userInfo.getTotalSpace());
redisUtils.setex(Constants.REDIS_KEY_USER_SPACE_USE + userId, spaceDto, Constants.REDIS_KEY_EXPIRES_DAY);
return spaceDto;
}
}
@@ -0,0 +1,79 @@
package com.easypan.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils<V> {
@Resource
private RedisTemplate<String, V> redisTemplate;
private static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public void delete(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}
public V get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, V value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
logger.error("设置redisKey:{},value:{}失败", key, value);
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean setex(String key, V value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
logger.error("设置redisKey:{},value:{}失败", key, value);
return false;
}
}
}
@@ -0,0 +1,71 @@
package com.easypan.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.math.BigDecimal;
@Slf4j
public class ScaleFilter {
public static Boolean createThumbnailWidthFFmpeg(File file, int thumbnailWidth, File targetFile, Boolean delSource) {
try {
BufferedImage src = ImageIO.read(file);
//thumbnailWidth 缩略图的宽度 thumbnailHeight 缩略图的高度
int sorceW = src.getWidth();
int sorceH = src.getHeight();
//小于 指定高宽不压缩
if (sorceW <= thumbnailWidth) {
return false;
}
compressImage(file, thumbnailWidth, targetFile, delSource);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void compressImageWidthPercentage(File sourceFile, BigDecimal widthPercentage, File targetFile) {
try {
BigDecimal widthResult = widthPercentage.multiply(new BigDecimal(ImageIO.read(sourceFile).getWidth()));
compressImage(sourceFile, widthResult.intValue(), targetFile, true);
} catch (Exception e) {
log.error("压缩图片失败");
}
}
public static void createCover4Video(File sourceFile, Integer width, File targetFile) {
try {
String cmd = "ffmpeg -i %s -y -vframes 1 -vf scale=%d:%d/a %s";
ProcessUtils.executeCommand(String.format(cmd, sourceFile.getAbsoluteFile(), width, width, targetFile.getAbsoluteFile()), false);
} catch (Exception e) {
log.error("生成视频封面失败", e);
}
}
public static void compressImage(File sourceFile, Integer width, File targetFile, Boolean delSource) {
try {
String cmd = "ffmpeg -i %s -vf scale=%d:-1 %s -y";
ProcessUtils.executeCommand(String.format(cmd, sourceFile.getAbsoluteFile(), width, targetFile.getAbsoluteFile()), false);
if (delSource) {
FileUtils.forceDelete(sourceFile);
}
} catch (Exception e) {
log.error("压缩图片失败");
}
}
public static void main(String[] args) {
compressImageWidthPercentage(new File("C:\\Users\\Administrator\\Pictures\\微信图片_20230107141436.png"), new BigDecimal(0.7),
new File("C:\\Users\\Administrator" +
"\\Pictures" +
"\\微信图片_202106281029182.jpg"));
}
}
@@ -0,0 +1,88 @@
package com.easypan.utils;
import com.easypan.entity.constants.Constants;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
public class StringTools {
public static String encodeByMD5(String originString) {
return StringTools.isEmpty(originString) ? null : DigestUtils.md5Hex(originString);
}
public static boolean isEmpty(String str) {
if (null == str || "".equals(str) || "null".equals(str) || "\u0000".equals(str)) {
return true;
} else if ("".equals(str.trim())) {
return true;
}
return false;
}
public static String getFileSuffix(String fileName) {
Integer index = fileName.lastIndexOf(".");
if (index == -1) {
return "";
}
String suffix = fileName.substring(index);
return suffix;
}
public static String getFileNameNoSuffix(String fileName) {
Integer index = fileName.lastIndexOf(".");
if (index == -1) {
return fileName;
}
fileName = fileName.substring(0, index);
return fileName;
}
public static String rename(String fileName) {
// 获取不加后缀的文件名
String fileNameReal = getFileNameNoSuffix(fileName);
// 获取文件的后缀名
String suffix = getFileSuffix(fileName);
return fileNameReal + "_" + getRandomString(Constants.LENGTH_5) + suffix;
}
public static final String getRandomString(Integer count) {
return RandomStringUtils.random(count, true, true);
}
public static final String getRandomNumber(Integer count) {
return RandomStringUtils.random(count, false, true);
}
public static String escapeTitle(String content) {
if (isEmpty(content)) {
return content;
}
content = content.replace("<", "&lt;");
return content;
}
public static String escapeHtml(String content) {
if (isEmpty(content)) {
return content;
}
content = content.replace("<", "&lt;");
content = content.replace(" ", "&nbsp;");
content = content.replace("\n", "<br>");
return content;
}
public static boolean pathIsOk(String path) {
if (StringTools.isEmpty(path)) {
return true;
}
if (path.contains("../") || path.contains("..\\")) {
return false;
}
return true;
}
}
@@ -0,0 +1,25 @@
package com.easypan.utils;
import com.easypan.entity.enums.VerifyRegexEnum;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class VerifyUtils {
public static boolean verify(String regex, String value) {
if (StringTools.isEmpty(value)) {
return false;
}
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(value);
return matcher.matches();
}
public static boolean verify(VerifyRegexEnum regex, String value) {
return verify(regex.getRegex(), value);
}
}
@@ -0,0 +1,54 @@
# 应用服务 WEB 访问端口
server.port=7090
server.servlet.context-path=/api
#session过期时间 60M 一个小时
server.servlet.session.timeout=PT60M
#处理favicon
spring.mvc.favicon.enable=false
#异常处理
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
#数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/pan?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=qgs123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#发送邮件配置相关
# 配置邮件服务器的地址 smtp.qq.com
spring.mail.host=smtp.qq.com
# 配置邮件服务器的端口(465或587)
spring.mail.port=465
# 配置用户的账号
spring.mail.username=2923503420@qq.com
# 配置用户的密码
spring.mail.password=***************
# 配置默认编码
spring.mail.default-encoding=UTF-8
# SSL 连接配置
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
# 开启 debug
spring.mail.properties.mail.debug=true
#邮件配置结束
#设置单个文件的大小
spring.servlet.multipart.max-file-size=10MB
#设置单次请求的文件的总大小
spring.servlet.multipart.max-request-size=10MB
#Spring redis配置
# Redis数据库索引(默认为0,端口6379)
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
# 连接超时时间(毫秒)
spring.redis.timeout=3000
#项目目录
project.folder=D:/Temp
#日志级别配置
log.root.level=info
#超级管理员id
admin.emails=1913324165@qq.com
@@ -0,0 +1,242 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.easypan.mappers.EmailCodeMapper">
<!--实体映射-->
<resultMap id="base_result_map" type="com.easypan.entity.po.EmailCode">
<!--邮箱-->
<result column="email" property="email"/>
<!--编号-->
<result column="code" property="code"/>
<!--创建时间-->
<result column="create_time" property="createTime"/>
<!--0:未使用 1:已使用-->
<result column="status" property="status"/>
</resultMap>
<!-- 通用查询结果列-->
<sql id="base_column_list">
email
,code,create_time,status
</sql>
<sql id="base_condition_filed">
<if test="query.email != null and query.email!=''">
and email = #{query.email}
</if>
<if test="query.code != null and query.code!=''">
and code = #{query.code}
</if>
<if test="query.createTime != null and query.createTime!=''">
<![CDATA[ and create_time=str_to_date(#{query.createTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.status != null">
and status = #{query.status}
</if>
</sql>
<!-- 通用条件列-->
<sql id="base_condition">
<where>
<include refid="base_condition_filed"/>
</where>
</sql>
<!-- 通用查询条件列-->
<sql id="query_condition">
<where>
<include refid="base_condition_filed"/>
<if test="query.emailFuzzy!= null and query.emailFuzzy!=''">
and email like concat('%', #{query.emailFuzzy}, '%')
</if>
<if test="query.codeFuzzy!= null and query.codeFuzzy!=''">
and code like concat('%', #{query.codeFuzzy}, '%')
</if>
<if test="query.createTimeStart!= null and query.createTimeStart!=''">
<![CDATA[ and create_time>=str_to_date(#{query.createTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.createTimeEnd!= null and query.createTimeEnd!=''">
<![CDATA[ and create_time< date_sub(str_to_date(#{query.createTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
</where>
</sql>
<!-- 查询集合-->
<select id="selectList" resultMap="base_result_map">
SELECT
<include refid="base_column_list"/>
FROM email_code
<include refid="query_condition"/>
<if test="query.orderBy!=null">
order by ${query.orderBy}
</if>
<if test="query.simplePage!=null">
limit #{query.simplePage.start},#{query.simplePage.end}
</if>
</select>
<!-- 查询数量-->
<select id="selectCount" resultType="java.lang.Integer">
SELECT count(1) FROM email_code
<include refid="query_condition"/>
</select>
<!-- 插入 (匹配有值的字段)-->
<insert id="insert" parameterType="com.easypan.entity.po.EmailCode">
INSERT INTO email_code
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.email != null">
email,
</if>
<if test="bean.code != null">
code,
</if>
<if test="bean.createTime != null">
create_time,
</if>
<if test="bean.status != null">
status,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.email!=null">
#{bean.email},
</if>
<if test="bean.code!=null">
#{bean.code},
</if>
<if test="bean.createTime!=null">
#{bean.createTime},
</if>
<if test="bean.status!=null">
#{bean.status},
</if>
</trim>
</insert>
<!-- 插入或者更新 (匹配有值的字段)-->
<insert id="insertOrUpdate" parameterType="com.easypan.entity.po.EmailCode">
INSERT INTO email_code
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.email != null">
email,
</if>
<if test="bean.code != null">
code,
</if>
<if test="bean.createTime != null">
create_time,
</if>
<if test="bean.status != null">
status,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.email!=null">
#{bean.email},
</if>
<if test="bean.code!=null">
#{bean.code},
</if>
<if test="bean.createTime!=null">
#{bean.createTime},
</if>
<if test="bean.status!=null">
#{bean.status},
</if>
</trim>
on DUPLICATE key update
<trim prefix="" suffix="" suffixOverrides=",">
<if test="bean.email!=null">
email = VALUES(email),
</if>
<if test="bean.code!=null">
code = VALUES(code),
</if>
<if test="bean.createTime!=null">
create_time = VALUES(create_time),
</if>
<if test="bean.status!=null">
status = VALUES(status),
</if>
</trim>
</insert>
<!-- 添加 (批量插入)-->
<insert id="insertBatch" parameterType="com.easypan.entity.po.EmailCode">
INSERT INTO email_code(
email,
code,
create_time,
status
)values
<foreach collection="list" item="item" separator=",">
(
#{item.email},
#{item.code},
#{item.createTime},
#{item.status}
)
</foreach>
</insert>
<!-- 批量新增修改 (批量插入)-->
<insert id="insertOrUpdateBatch" parameterType="com.easypan.entity.po.EmailCode">
INSERT INTO email_code(
email,
code,
create_time,
status
)values
<foreach collection="list" item="item" separator=",">
(
#{item.email},
#{item.code},
#{item.createTime},
#{item.status}
)
</foreach>
on DUPLICATE key update
email = VALUES(email),
code = VALUES(code),
create_time = VALUES(create_time),
status = VALUES(status)
</insert>
<!-- 根据EmailAndCode修改-->
<update id="updateByEmailAndCode" parameterType="com.easypan.entity.po.EmailCode">
UPDATE email_code
<set>
<if test="bean.createTime != null">
create_time = #{bean.createTime},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
</set>
where email=#{email} and code=#{code}
</update>
<!-- 根据EmailAndCode删除-->
<delete id="deleteByEmailAndCode">
delete
from email_code
where email = #{email}
and code = #{code}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByEmailAndCode" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from email_code where email=#{email} and code=#{code}
</select>
<update id="disableEmailCode">
update email_code
set status = 1
where email = #{email}
and status = 0
</update>
</mapper>
@@ -0,0 +1,759 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.easypan.mappers.FileInfoMapper">
<!--实体映射-->
<resultMap id="base_result_map" type="com.easypan.entity.po.FileInfo">
<!--文件ID-->
<result column="file_id" property="fileId"/>
<!--用户ID-->
<result column="user_id" property="userId"/>
<!--md5值,第一次上传记录-->
<result column="file_md5" property="fileMd5"/>
<!--父级ID-->
<result column="file_pid" property="filePid"/>
<!--文件大小-->
<result column="file_size" property="fileSize"/>
<!--文件名称-->
<result column="file_name" property="fileName"/>
<!--封面-->
<result column="file_cover" property="fileCover"/>
<!--文件路径-->
<result column="file_path" property="filePath"/>
<!--创建时间-->
<result column="create_time" property="createTime"/>
<!--最后更新时间-->
<result column="last_update_time" property="lastUpdateTime"/>
<!--0:文件 1:目录-->
<result column="folder_type" property="folderType"/>
<!--1:视频 2:音频 3:图片 4:文档 5:其他-->
<result column="file_category" property="fileCategory"/>
<!-- 1:视频 2:音频 3:图片 4:pdf 5:doc 6:excel 7:txt 8:code 9:zip 10:其他-->
<result column="file_type" property="fileType"/>
<!--0:转码中 1转码失败 2:转码成功-->
<result column="status" property="status"/>
<!--回收站时间-->
<result column="recovery_time" property="recoveryTime"/>
<!--删除标记 0:删除 1:回收站 2:正常-->
<result column="del_flag" property="delFlag"/>
</resultMap>
<!-- 通用查询结果列-->
<sql id="base_column_list">
file_id
,user_id,file_md5,file_pid,file_size,
file_name,file_cover,file_path,create_time,last_update_time,
folder_type,file_category,file_type,status,recovery_time,
del_flag
</sql>
<sql id="base_condition_filed">
<if test="query.fileId != null and query.fileId!=''">
and file_id = #{query.fileId}
</if>
<if test="query.userId != null and query.userId!=''">
and user_id = #{query.userId}
</if>
<if test="query.fileMd5 != null and query.fileMd5!=''">
and file_md5 = #{query.fileMd5}
</if>
<if test="query.filePid != null and query.filePid!=''">
and file_pid = #{query.filePid}
</if>
<if test="query.fileSize != null">
and file_size = #{query.fileSize}
</if>
<if test="query.fileName != null and query.fileName!=''">
and file_name = #{query.fileName}
</if>
<if test="query.fileCover != null and query.fileCover!=''">
and file_cover = #{query.fileCover}
</if>
<if test="query.filePath != null and query.filePath!=''">
and file_path = #{query.filePath}
</if>
<if test="query.createTime != null and query.createTime!=''">
<![CDATA[ and create_time=str_to_date(#{query.createTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.lastUpdateTime != null and query.lastUpdateTime!=''">
<![CDATA[ and last_update_time=str_to_date(#{query.lastUpdateTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.folderType != null">
and folder_type = #{query.folderType}
</if>
<if test="query.fileCategory != null">
and file_category = #{query.fileCategory}
</if>
<if test="query.fileType != null">
and file_type = #{query.fileType}
</if>
<if test="query.status != null">
and status = #{query.status}
</if>
<if test="query.recoveryTime != null and query.recoveryTime!=''">
<![CDATA[ and recovery_time=str_to_date(#{query.recoveryTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.delFlag != null">
and del_flag = #{query.delFlag}
</if>
<if test="query.fileIdArray!=null and query.fileIdArray.length>0">
and file_id in(<foreach collection="query.fileIdArray" item="item" separator=",">#{item}</foreach>)
</if>
<if test="query.filePidArray!=null and query.filePidArray.length>0">
and file_pid in(<foreach collection="query.filePidArray" item="item" separator=",">#{item}</foreach>)
</if>
<if test="query.excludeFileIdArray!=null and query.excludeFileIdArray.length>0">
and file_id not in(<foreach collection="query.excludeFileIdArray" separator="," item="item">
#{item}</foreach>)
</if>
</sql>
<!-- 通用条件列-->
<sql id="base_condition">
<where>
<include refid="base_condition_filed"/>
</where>
</sql>
<!-- 通用查询条件列-->
<sql id="query_condition">
<where>
<include refid="base_condition_filed"/>
<if test="query.fileIdFuzzy!= null and query.fileIdFuzzy!=''">
and file_id like concat('%', #{query.fileIdFuzzy}, '%')
</if>
<if test="query.userIdFuzzy!= null and query.userIdFuzzy!=''">
and user_id like concat('%', #{query.userIdFuzzy}, '%')
</if>
<if test="query.fileMd5Fuzzy!= null and query.fileMd5Fuzzy!=''">
and file_md5 like concat('%', #{query.fileMd5Fuzzy}, '%')
</if>
<if test="query.filePidFuzzy!= null and query.filePidFuzzy!=''">
and file_pid like concat('%', #{query.filePidFuzzy}, '%')
</if>
<if test="query.fileNameFuzzy!= null and query.fileNameFuzzy!=''">
and file_name like concat('%', #{query.fileNameFuzzy}, '%')
</if>
<if test="query.fileCoverFuzzy!= null and query.fileCoverFuzzy!=''">
and file_cover like concat('%', #{query.fileCoverFuzzy}, '%')
</if>
<if test="query.filePathFuzzy!= null and query.filePathFuzzy!=''">
and file_path like concat('%', #{query.filePathFuzzy}, '%')
</if>
<if test="query.createTimeStart!= null and query.createTimeStart!=''">
<![CDATA[ and create_time>=str_to_date(#{query.createTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.createTimeEnd!= null and query.createTimeEnd!=''">
<![CDATA[ and create_time< date_sub(str_to_date(#{query.createTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
<if test="query.lastUpdateTimeStart!= null and query.lastUpdateTimeStart!=''">
<![CDATA[ and last_update_time>=str_to_date(#{query.lastUpdateTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.lastUpdateTimeEnd!= null and query.lastUpdateTimeEnd!=''">
<![CDATA[ and last_update_time< date_sub(str_to_date(#{query.lastUpdateTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
<if test="query.recoveryTimeStart!= null and query.recoveryTimeStart!=''">
<![CDATA[ and recovery_time>=str_to_date(#{query.recoveryTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.recoveryTimeEnd!= null and query.recoveryTimeEnd!=''">
<![CDATA[ and recovery_time< date_sub(str_to_date(#{query.recoveryTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
<if test="query.queryExpire!=null and query.queryExpire">
<![CDATA[ and recovery_time< date_sub(now(),interval 10 day)]]>
</if>
</where>
</sql>
<!-- 查询集合-->
<select id="selectList" resultMap="base_result_map">
SELECT
<include refid="base_column_list"/>
<if test="query.queryNickName!=null and query.queryNickName">
,(select nick_name from user_info u where u.user_id = f.user_id) nickName
</if>
FROM file_info f
<include refid="query_condition"/>
<if test="query.orderBy!=null">
order by ${query.orderBy}
</if>
<if test="query.simplePage!=null">
limit #{query.simplePage.start},#{query.simplePage.end}
</if>
</select>
<!-- 查询数量-->
<select id="selectCount" resultType="java.lang.Integer">
SELECT count(1) FROM file_info
<include refid="query_condition"/>
</select>
<!-- 插入 (匹配有值的字段)-->
<insert id="insert" parameterType="com.easypan.entity.po.FileInfo">
INSERT INTO file_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.fileId != null">
file_id,
</if>
<if test="bean.userId != null">
user_id,
</if>
<if test="bean.fileMd5 != null">
file_md5,
</if>
<if test="bean.filePid != null">
file_pid,
</if>
<if test="bean.fileSize != null">
file_size,
</if>
<if test="bean.fileName != null">
file_name,
</if>
<if test="bean.fileCover != null">
file_cover,
</if>
<if test="bean.filePath != null">
file_path,
</if>
<if test="bean.createTime != null">
create_time,
</if>
<if test="bean.lastUpdateTime != null">
last_update_time,
</if>
<if test="bean.folderType != null">
folder_type,
</if>
<if test="bean.fileCategory != null">
file_category,
</if>
<if test="bean.fileType != null">
file_type,
</if>
<if test="bean.status != null">
status,
</if>
<if test="bean.recoveryTime != null">
recovery_time,
</if>
<if test="bean.delFlag != null">
del_flag,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.fileId!=null">
#{bean.fileId},
</if>
<if test="bean.userId!=null">
#{bean.userId},
</if>
<if test="bean.fileMd5!=null">
#{bean.fileMd5},
</if>
<if test="bean.filePid!=null">
#{bean.filePid},
</if>
<if test="bean.fileSize!=null">
#{bean.fileSize},
</if>
<if test="bean.fileName!=null">
#{bean.fileName},
</if>
<if test="bean.fileCover!=null">
#{bean.fileCover},
</if>
<if test="bean.filePath!=null">
#{bean.filePath},
</if>
<if test="bean.createTime!=null">
#{bean.createTime},
</if>
<if test="bean.lastUpdateTime!=null">
#{bean.lastUpdateTime},
</if>
<if test="bean.folderType!=null">
#{bean.folderType},
</if>
<if test="bean.fileCategory!=null">
#{bean.fileCategory},
</if>
<if test="bean.fileType!=null">
#{bean.fileType},
</if>
<if test="bean.status!=null">
#{bean.status},
</if>
<if test="bean.recoveryTime!=null">
#{bean.recoveryTime},
</if>
<if test="bean.delFlag!=null">
#{bean.delFlag},
</if>
</trim>
</insert>
<!-- 插入或者更新 (匹配有值的字段)-->
<insert id="insertOrUpdate" parameterType="com.easypan.entity.po.FileInfo">
INSERT INTO file_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.fileId != null">
file_id,
</if>
<if test="bean.userId != null">
user_id,
</if>
<if test="bean.fileMd5 != null">
file_md5,
</if>
<if test="bean.filePid != null">
file_pid,
</if>
<if test="bean.fileSize != null">
file_size,
</if>
<if test="bean.fileName != null">
file_name,
</if>
<if test="bean.fileCover != null">
file_cover,
</if>
<if test="bean.filePath != null">
file_path,
</if>
<if test="bean.createTime != null">
create_time,
</if>
<if test="bean.lastUpdateTime != null">
last_update_time,
</if>
<if test="bean.folderType != null">
folder_type,
</if>
<if test="bean.fileCategory != null">
file_category,
</if>
<if test="bean.fileType != null">
file_type,
</if>
<if test="bean.status != null">
status,
</if>
<if test="bean.recoveryTime != null">
recovery_time,
</if>
<if test="bean.delFlag != null">
del_flag,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.fileId!=null">
#{bean.fileId},
</if>
<if test="bean.userId!=null">
#{bean.userId},
</if>
<if test="bean.fileMd5!=null">
#{bean.fileMd5},
</if>
<if test="bean.filePid!=null">
#{bean.filePid},
</if>
<if test="bean.fileSize!=null">
#{bean.fileSize},
</if>
<if test="bean.fileName!=null">
#{bean.fileName},
</if>
<if test="bean.fileCover!=null">
#{bean.fileCover},
</if>
<if test="bean.filePath!=null">
#{bean.filePath},
</if>
<if test="bean.createTime!=null">
#{bean.createTime},
</if>
<if test="bean.lastUpdateTime!=null">
#{bean.lastUpdateTime},
</if>
<if test="bean.folderType!=null">
#{bean.folderType},
</if>
<if test="bean.fileCategory!=null">
#{bean.fileCategory},
</if>
<if test="bean.fileType!=null">
#{bean.fileType},
</if>
<if test="bean.status!=null">
#{bean.status},
</if>
<if test="bean.recoveryTime!=null">
#{bean.recoveryTime},
</if>
<if test="bean.delFlag!=null">
#{bean.delFlag},
</if>
</trim>
on DUPLICATE key update
<trim prefix="" suffix="" suffixOverrides=",">
<if test="bean.fileId!=null">
file_id = VALUES(file_id),
</if>
<if test="bean.userId!=null">
user_id = VALUES(user_id),
</if>
<if test="bean.fileMd5!=null">
file_md5 = VALUES(file_md5),
</if>
<if test="bean.filePid!=null">
file_pid = VALUES(file_pid),
</if>
<if test="bean.fileSize!=null">
file_size = VALUES(file_size),
</if>
<if test="bean.fileName!=null">
file_name = VALUES(file_name),
</if>
<if test="bean.fileCover!=null">
file_cover = VALUES(file_cover),
</if>
<if test="bean.filePath!=null">
file_path = VALUES(file_path),
</if>
<if test="bean.createTime!=null">
create_time = VALUES(create_time),
</if>
<if test="bean.lastUpdateTime!=null">
last_update_time = VALUES(last_update_time),
</if>
<if test="bean.folderType!=null">
folder_type = VALUES(folder_type),
</if>
<if test="bean.fileCategory!=null">
file_category = VALUES(file_category),
</if>
<if test="bean.fileType!=null">
file_type = VALUES(file_type),
</if>
<if test="bean.status!=null">
status = VALUES(status),
</if>
<if test="bean.recoveryTime!=null">
recovery_time = VALUES(recovery_time),
</if>
<if test="bean.delFlag!=null">
del_flag = VALUES(del_flag),
</if>
</trim>
</insert>
<!-- 添加 (批量插入)-->
<insert id="insertBatch" parameterType="com.easypan.entity.po.FileInfo">
INSERT INTO file_info(
file_id,
user_id,
file_md5,
file_pid,
file_size,
file_name,
file_cover,
file_path,
create_time,
last_update_time,
folder_type,
file_category,
file_type,
status,
recovery_time,
del_flag
)values
<foreach collection="list" item="item" separator=",">
(
#{item.fileId},
#{item.userId},
#{item.fileMd5},
#{item.filePid},
#{item.fileSize},
#{item.fileName},
#{item.fileCover},
#{item.filePath},
#{item.createTime},
#{item.lastUpdateTime},
#{item.folderType},
#{item.fileCategory},
#{item.fileType},
#{item.status},
#{item.recoveryTime},
#{item.delFlag}
)
</foreach>
</insert>
<!-- 批量新增修改 (批量插入)-->
<insert id="insertOrUpdateBatch" parameterType="com.easypan.entity.po.FileInfo">
INSERT INTO file_info(
file_id,
user_id,
file_md5,
file_pid,
file_size,
file_name,
file_cover,
file_path,
create_time,
last_update_time,
folder_type,
file_category,
file_type,
status,
recovery_time,
del_flag
)values
<foreach collection="list" item="item" separator=",">
(
#{item.fileId},
#{item.userId},
#{item.fileMd5},
#{item.filePid},
#{item.fileSize},
#{item.fileName},
#{item.fileCover},
#{item.filePath},
#{item.createTime},
#{item.lastUpdateTime},
#{item.folderType},
#{item.fileCategory},
#{item.fileType},
#{item.status},
#{item.recoveryTime},
#{item.delFlag}
)
</foreach>
on DUPLICATE key update
file_id = VALUES(file_id),
user_id = VALUES(user_id),
file_md5 = VALUES(file_md5),
file_pid = VALUES(file_pid),
file_size = VALUES(file_size),
file_name = VALUES(file_name),
file_cover = VALUES(file_cover),
file_path = VALUES(file_path),
create_time = VALUES(create_time),
last_update_time = VALUES(last_update_time),
folder_type = VALUES(folder_type),
file_category = VALUES(file_category),
file_type = VALUES(file_type),
status = VALUES(status),
recovery_time = VALUES(recovery_time),
del_flag = VALUES(del_flag)
</insert>
<!-- 根据FileIdAndUserId修改-->
<update id="updateByFileIdAndUserId" parameterType="com.easypan.entity.po.FileInfo">
UPDATE file_info
<set>
<if test="bean.fileMd5 != null">
file_md5 = #{bean.fileMd5},
</if>
<if test="bean.filePid != null">
file_pid = #{bean.filePid},
</if>
<if test="bean.fileSize != null">
file_size = #{bean.fileSize},
</if>
<if test="bean.fileName != null">
file_name = #{bean.fileName},
</if>
<if test="bean.fileCover != null">
file_cover = #{bean.fileCover},
</if>
<if test="bean.filePath != null">
file_path = #{bean.filePath},
</if>
<if test="bean.createTime != null">
create_time = #{bean.createTime},
</if>
<if test="bean.lastUpdateTime != null">
last_update_time = #{bean.lastUpdateTime},
</if>
<if test="bean.folderType != null">
folder_type = #{bean.folderType},
</if>
<if test="bean.fileCategory != null">
file_category = #{bean.fileCategory},
</if>
<if test="bean.fileType != null">
file_type = #{bean.fileType},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.recoveryTime != null">
recovery_time = #{bean.recoveryTime},
</if>
<if test="bean.delFlag != null">
del_flag = #{bean.delFlag},
</if>
</set>
where file_id=#{fileId} and user_id=#{userId}
</update>
<!-- 根据FileIdAndUserId删除-->
<delete id="deleteByFileIdAndUserId">
delete
from file_info
where file_id = #{fileId}
and user_id = #{userId}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByFileIdAndUserId" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from file_info where file_id=#{fileId} and user_id=#{userId}
</select>
<update id="updateFileStatusWithOldStatus">
update file_info
<set>
<if test="bean.fileMd5 != null">
file_md5 = #{bean.fileMd5},
</if>
<if test="bean.filePid != null">
file_pid = #{bean.filePid},
</if>
<if test="bean.fileSize != null">
file_size = #{bean.fileSize},
</if>
<if test="bean.fileName != null">
file_name = #{bean.fileName},
</if>
<if test="bean.fileCover != null">
file_cover = #{bean.fileCover},
</if>
<if test="bean.filePath != null">
file_path = #{bean.filePath},
</if>
<if test="bean.createTime != null">
create_time = #{bean.createTime},
</if>
<if test="bean.lastUpdateTime != null">
last_update_time = #{bean.lastUpdateTime},
</if>
<if test="bean.folderType != null">
folder_type = #{bean.folderType},
</if>
<if test="bean.fileCategory != null">
file_category = #{bean.fileCategory},
</if>
<if test="bean.fileType != null">
file_type = #{bean.fileType},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.recoveryTime != null">
recovery_time = #{bean.recoveryTime},
</if>
<if test="bean.delFlag != null">
del_flag = #{bean.delFlag},
</if>
</set>
where file_id = #{fileId}
and user_id = #{userId}
and status = #{oldStatus}
</update>
<update id="updateFileDelFlagBatch">
update file_info
<set>
<if test="bean.fileMd5 != null">
file_md5 = #{bean.fileMd5},
</if>
<if test="bean.filePid != null">
file_pid = #{bean.filePid},
</if>
<if test="bean.fileSize != null">
file_size = #{bean.fileSize},
</if>
<if test="bean.fileName != null">
file_name = #{bean.fileName},
</if>
<if test="bean.fileCover != null">
file_cover = #{bean.fileCover},
</if>
<if test="bean.filePath != null">
file_path = #{bean.filePath},
</if>
<if test="bean.createTime != null">
create_time = #{bean.createTime},
</if>
<if test="bean.lastUpdateTime != null">
last_update_time = #{bean.lastUpdateTime},
</if>
<if test="bean.folderType != null">
folder_type = #{bean.folderType},
</if>
<if test="bean.fileCategory != null">
file_category = #{bean.fileCategory},
</if>
<if test="bean.fileType != null">
file_type = #{bean.fileType},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.recoveryTime != null">
recovery_time = #{bean.recoveryTime},
</if>
<if test="bean.delFlag != null">
del_flag = #{bean.delFlag},
</if>
</set>
where user_id = #{userId}
<if test="filePidList!=null">
and file_pid in(<foreach collection="filePidList" separator="," item="item">#{item}</foreach>)
</if>
<if test="fileIdList!=null">
and file_id in(<foreach collection="fileIdList" separator="," item="item">#{item}</foreach>)
</if>
<if test="oldDelFlag!=null">
and del_flag = #{oldDelFlag}
</if>
</update>
<delete id="delFileBatch">
delete from file_info where user_id = #{userId}
<if test="filePidList!=null">
and file_pid in(<foreach collection="filePidList" separator="," item="item">#{item}</foreach>)
</if>
<if test="fileIdList!=null">
and file_id in(<foreach collection="fileIdList" separator="," item="item">#{item}</foreach>)
</if>
<if test="oldDelFlag!=null">
and del_flag = #{oldDelFlag}
</if>
</delete>
<select id="selectUseSpace" resultType="java.lang.Long">
select IFNULL(sum(file_size), 0)
from file_info
where user_id = #{userId}
</select>
<delete id="deleteFileByUserId">
delete
from file_info
where user_id = #{userId}
</delete>
<!-- <select id="selectUseSpace">-->
<!-- select NULLIF(0, sum(file_size))-->
<!-- from file_info-->
<!-- where user_id = #{userId}-->
<!-- </select>-->
</mapper>
@@ -0,0 +1,389 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.easypan.mappers.FileShareMapper">
<!--实体映射-->
<resultMap id="base_result_map" type="com.easypan.entity.po.FileShare">
<!--分享ID-->
<result column="share_id" property="shareId"/>
<!--文件ID-->
<result column="file_id" property="fileId"/>
<!--用户ID-->
<result column="user_id" property="userId"/>
<!--有效期类型 0:1天 1:7天 2:30天 3:永久有效-->
<result column="valid_type" property="validType"/>
<!--失效时间-->
<result column="expire_time" property="expireTime"/>
<!--分享时间-->
<result column="share_time" property="shareTime"/>
<!--提取码-->
<result column="code" property="code"/>
<!--浏览次数-->
<result column="show_count" property="showCount"/>
<!--文件名称-->
<result column="file_name" property="fileName"/>
<!--封面-->
<result column="file_cover" property="fileCover"/>
<!--0:文件 1:目录-->
<result column="folder_type" property="folderType"/>
<!--1:视频 2:音频 3:图片 4:文档 5:其他-->
<result column="file_category" property="fileCategory"/>
<!-- 1:视频 2:音频 3:图片 4:pdf 5:doc 6:excel 7:txt 8:code 9:zip 10:其他-->
<result column="file_type" property="fileType"/>
</resultMap>
<!-- 通用查询结果列-->
<sql id="base_column_list">
share_id
,s.file_id,s.user_id,valid_type,expire_time,
share_time,code,show_count
</sql>
<sql id="base_condition_filed">
<if test="query.shareId != null and query.shareId!=''">
and share_id = #{query.shareId}
</if>
<if test="query.fileId != null and query.fileId!=''">
and s.file_id = #{query.fileId}
</if>
<if test="query.userId != null and query.userId!=''">
and s.user_id = #{query.userId}
</if>
<if test="query.validType != null">
and valid_type = #{query.validType}
</if>
<if test="query.expireTime != null and query.expireTime!=''">
<![CDATA[ and expire_time=str_to_date(#{query.expireTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.shareTime != null and query.shareTime!=''">
<![CDATA[ and share_time=str_to_date(#{query.shareTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.code != null and query.code!=''">
and code = #{query.code}
</if>
<if test="query.showCount != null">
and show_count = #{query.showCount}
</if>
</sql>
<!-- 通用条件列-->
<sql id="base_condition">
<where>
<include refid="base_condition_filed"/>
</where>
</sql>
<!-- 通用查询条件列-->
<sql id="query_condition">
<where>
<include refid="base_condition_filed"/>
<if test="query.shareIdFuzzy!= null and query.shareIdFuzzy!=''">
and share_id like concat('%', #{query.shareIdFuzzy}, '%')
</if>
<if test="query.fileIdFuzzy!= null and query.fileIdFuzzy!=''">
and s.file_id like concat('%', #{query.fileIdFuzzy}, '%')
</if>
<if test="query.userIdFuzzy!= null and query.userIdFuzzy!=''">
and s.user_id like concat('%', #{query.userIdFuzzy}, '%')
</if>
<if test="query.expireTimeStart!= null and query.expireTimeStart!=''">
<![CDATA[ and expire_time>=str_to_date(#{query.expireTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.expireTimeEnd!= null and query.expireTimeEnd!=''">
<![CDATA[ and expire_time< date_sub(str_to_date(#{query.expireTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
<if test="query.shareTimeStart!= null and query.shareTimeStart!=''">
<![CDATA[ and share_time>=str_to_date(#{query.shareTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.shareTimeEnd!= null and query.shareTimeEnd!=''">
<![CDATA[ and share_time< date_sub(str_to_date(#{query.shareTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
<if test="query.codeFuzzy!= null and query.codeFuzzy!=''">
and code like concat('%', #{query.codeFuzzy}, '%')
</if>
</where>
</sql>
<!-- 查询集合-->
<select id="selectList" resultMap="base_result_map">
SELECT
<include refid="base_column_list"/>
<if test="query.queryFileName!=null and query.queryFileName">
,f.file_name,f.folder_type,f.file_category,f.file_type,f.file_cover
</if>
FROM file_share s
<if test="query.queryFileName!=null and query.queryFileName">
left join file_info f on s.file_id = f.file_id and f.user_id = #{query.userId}
</if>
<include refid="query_condition"/>
<if test="query.orderBy!=null">
order by ${query.orderBy}
</if>
<if test="query.simplePage!=null">
limit #{query.simplePage.start},#{query.simplePage.end}
</if>
</select>
<!-- 查询数量-->
<select id="selectCount" resultType="java.lang.Integer">
SELECT count(1) FROM file_share s
<include refid="query_condition"/>
</select>
<!-- 插入 (匹配有值的字段)-->
<insert id="insert" parameterType="com.easypan.entity.po.FileShare">
INSERT INTO file_share
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.shareId != null">
share_id,
</if>
<if test="bean.fileId != null">
file_id,
</if>
<if test="bean.userId != null">
user_id,
</if>
<if test="bean.validType != null">
valid_type,
</if>
<if test="bean.expireTime != null">
expire_time,
</if>
<if test="bean.shareTime != null">
share_time,
</if>
<if test="bean.code != null">
code,
</if>
<if test="bean.showCount != null">
show_count,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.shareId!=null">
#{bean.shareId},
</if>
<if test="bean.fileId!=null">
#{bean.fileId},
</if>
<if test="bean.userId!=null">
#{bean.userId},
</if>
<if test="bean.validType!=null">
#{bean.validType},
</if>
<if test="bean.expireTime!=null">
#{bean.expireTime},
</if>
<if test="bean.shareTime!=null">
#{bean.shareTime},
</if>
<if test="bean.code!=null">
#{bean.code},
</if>
<if test="bean.showCount!=null">
#{bean.showCount},
</if>
</trim>
</insert>
<!-- 插入或者更新 (匹配有值的字段)-->
<insert id="insertOrUpdate" parameterType="com.easypan.entity.po.FileShare">
INSERT INTO file_share
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.shareId != null">
share_id,
</if>
<if test="bean.fileId != null">
file_id,
</if>
<if test="bean.userId != null">
user_id,
</if>
<if test="bean.validType != null">
valid_type,
</if>
<if test="bean.expireTime != null">
expire_time,
</if>
<if test="bean.shareTime != null">
share_time,
</if>
<if test="bean.code != null">
code,
</if>
<if test="bean.showCount != null">
show_count,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.shareId!=null">
#{bean.shareId},
</if>
<if test="bean.fileId!=null">
#{bean.fileId},
</if>
<if test="bean.userId!=null">
#{bean.userId},
</if>
<if test="bean.validType!=null">
#{bean.validType},
</if>
<if test="bean.expireTime!=null">
#{bean.expireTime},
</if>
<if test="bean.shareTime!=null">
#{bean.shareTime},
</if>
<if test="bean.code!=null">
#{bean.code},
</if>
<if test="bean.showCount!=null">
#{bean.showCount},
</if>
</trim>
on DUPLICATE key update
<trim prefix="" suffix="" suffixOverrides=",">
<if test="bean.shareId!=null">
share_id = VALUES(share_id),
</if>
<if test="bean.fileId!=null">
file_id = VALUES(file_id),
</if>
<if test="bean.userId!=null">
user_id = VALUES(user_id),
</if>
<if test="bean.validType!=null">
valid_type = VALUES(valid_type),
</if>
<if test="bean.expireTime!=null">
expire_time = VALUES(expire_time),
</if>
<if test="bean.shareTime!=null">
share_time = VALUES(share_time),
</if>
<if test="bean.code!=null">
code = VALUES(code),
</if>
<if test="bean.showCount!=null">
show_count = VALUES(show_count),
</if>
</trim>
</insert>
<!-- 添加 (批量插入)-->
<insert id="insertBatch" parameterType="com.easypan.entity.po.FileShare">
INSERT INTO file_share(
share_id,
file_id,
user_id,
valid_type,
expire_time,
share_time,
code,
show_count
)values
<foreach collection="list" item="item" separator=",">
(
#{item.shareId},
#{item.fileId},
#{item.userId},
#{item.validType},
#{item.expireTime},
#{item.shareTime},
#{item.code},
#{item.showCount}
)
</foreach>
</insert>
<!-- 批量新增修改 (批量插入)-->
<insert id="insertOrUpdateBatch" parameterType="com.easypan.entity.po.FileShare">
INSERT INTO file_share(
share_id,
file_id,
user_id,
valid_type,
expire_time,
share_time,
code,
show_count
)values
<foreach collection="list" item="item" separator=",">
(
#{item.shareId},
#{item.fileId},
#{item.userId},
#{item.validType},
#{item.expireTime},
#{item.shareTime},
#{item.code},
#{item.showCount}
)
</foreach>
on DUPLICATE key update
share_id = VALUES(share_id),
file_id = VALUES(file_id),
user_id = VALUES(user_id),
valid_type = VALUES(valid_type),
expire_time = VALUES(expire_time),
share_time = VALUES(share_time),
code = VALUES(code),
show_count = VALUES(show_count)
</insert>
<!-- 根据ShareId修改-->
<update id="updateByShareId" parameterType="com.easypan.entity.po.FileShare">
UPDATE file_share
<set>
<if test="bean.fileId != null">
file_id = #{bean.fileId},
</if>
<if test="bean.userId != null">
user_id = #{bean.userId},
</if>
<if test="bean.validType != null">
valid_type = #{bean.validType},
</if>
<if test="bean.expireTime != null">
expire_time = #{bean.expireTime},
</if>
<if test="bean.shareTime != null">
share_time = #{bean.shareTime},
</if>
<if test="bean.code != null">
code = #{bean.code},
</if>
<if test="bean.showCount != null">
show_count = #{bean.showCount},
</if>
</set>
where share_id=#{shareId}
</update>
<!-- 根据ShareId删除-->
<delete id="deleteByShareId">
delete
from file_share
where share_id = #{shareId}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByShareId" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from file_share s where share_id=#{shareId}
</select>
<delete id="deleteFileShareBatch">
delete from file_share where user_id = #{userId}
and share_id in(<foreach collection="shareIdArray" separator="," item="item">#{item}</foreach>)
</delete>
<update id="updateShareShowCount">
update file_share
set show_count = show_count + 1
where share_id = #{shareId}
</update>
</mapper>
@@ -0,0 +1,628 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.easypan.mappers.UserInfoMapper">
<!--实体映射-->
<resultMap id="base_result_map" type="com.easypan.entity.po.UserInfo">
<!--用户ID-->
<result column="user_id" property="userId"/>
<!--昵称-->
<result column="nick_name" property="nickName"/>
<!--邮箱-->
<result column="email" property="email"/>
<!--qqOpenID-->
<result column="qq_open_id" property="qqOpenId"/>
<!--qq头像-->
<result column="qq_avatar" property="qqAvatar"/>
<!--密码-->
<result column="password" property="password"/>
<!--加入时间-->
<result column="join_time" property="joinTime"/>
<!--最后登录时间-->
<result column="last_login_time" property="lastLoginTime"/>
<!--0:禁用 1:正常-->
<result column="status" property="status"/>
<!--使用空间单位byte-->
<result column="use_space" property="useSpace"/>
<!--总空间-->
<result column="total_space" property="totalSpace"/>
</resultMap>
<!-- 通用查询结果列-->
<sql id="base_column_list">
user_id
,nick_name,email,qq_open_id,qq_avatar,
password,join_time,last_login_time,status,use_space,
total_space
</sql>
<sql id="base_condition_filed">
<if test="query.userId != null and query.userId!=''">
and user_id = #{query.userId}
</if>
<if test="query.nickName != null and query.nickName!=''">
and nick_name = #{query.nickName}
</if>
<if test="query.email != null and query.email!=''">
and email = #{query.email}
</if>
<if test="query.qqOpenId != null and query.qqOpenId!=''">
and qq_open_id = #{query.qqOpenId}
</if>
<if test="query.qqAvatar != null and query.qqAvatar!=''">
and qq_avatar = #{query.qqAvatar}
</if>
<if test="query.password != null and query.password!=''">
and password = #{query.password}
</if>
<if test="query.joinTime != null and query.joinTime!=''">
<![CDATA[ and join_time=str_to_date(#{query.joinTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.lastLoginTime != null and query.lastLoginTime!=''">
<![CDATA[ and last_login_time=str_to_date(#{query.lastLoginTime}, '%Y-%m-%d') ]]>
</if>
<if test="query.status != null">
and status = #{query.status}
</if>
<if test="query.useSpace != null">
and use_space = #{query.useSpace}
</if>
<if test="query.totalSpace != null">
and total_space = #{query.totalSpace}
</if>
</sql>
<!-- 通用条件列-->
<sql id="base_condition">
<where>
<include refid="base_condition_filed"/>
</where>
</sql>
<!-- 通用查询条件列-->
<sql id="query_condition">
<where>
<include refid="base_condition_filed"/>
<if test="query.userIdFuzzy!= null and query.userIdFuzzy!=''">
and user_id like concat('%', #{query.userIdFuzzy}, '%')
</if>
<if test="query.nickNameFuzzy!= null and query.nickNameFuzzy!=''">
and nick_name like concat('%', #{query.nickNameFuzzy}, '%')
</if>
<if test="query.emailFuzzy!= null and query.emailFuzzy!=''">
and email like concat('%', #{query.emailFuzzy}, '%')
</if>
<if test="query.qqOpenIdFuzzy!= null and query.qqOpenIdFuzzy!=''">
and qq_open_id like concat('%', #{query.qqOpenIdFuzzy}, '%')
</if>
<if test="query.qqAvatarFuzzy!= null and query.qqAvatarFuzzy!=''">
and qq_avatar like concat('%', #{query.qqAvatarFuzzy}, '%')
</if>
<if test="query.passwordFuzzy!= null and query.passwordFuzzy!=''">
and password like concat('%', #{query.passwordFuzzy}, '%')
</if>
<if test="query.joinTimeStart!= null and query.joinTimeStart!=''">
<![CDATA[ and join_time>=str_to_date(#{query.joinTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.joinTimeEnd!= null and query.joinTimeEnd!=''">
<![CDATA[ and join_time< date_sub(str_to_date(#{query.joinTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
<if test="query.lastLoginTimeStart!= null and query.lastLoginTimeStart!=''">
<![CDATA[ and last_login_time>=str_to_date(#{query.lastLoginTimeStart}, '%Y-%m-%d') ]]>
</if>
<if test="query.lastLoginTimeEnd!= null and query.lastLoginTimeEnd!=''">
<![CDATA[ and last_login_time< date_sub(str_to_date(#{query.lastLoginTimeEnd},'%Y-%m-%d'),interval -1 day) ]]>
</if>
</where>
</sql>
<!-- 查询集合-->
<select id="selectList" resultMap="base_result_map">
SELECT
<include refid="base_column_list"/>
FROM user_info
<include refid="query_condition"/>
<if test="query.orderBy!=null">
order by ${query.orderBy}
</if>
<if test="query.simplePage!=null">
limit #{query.simplePage.start},#{query.simplePage.end}
</if>
</select>
<!-- 查询数量-->
<select id="selectCount" resultType="java.lang.Integer">
SELECT count(1) FROM user_info
<include refid="query_condition"/>
</select>
<!-- 插入 (匹配有值的字段)-->
<insert id="insert" parameterType="com.easypan.entity.po.UserInfo">
INSERT INTO user_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.userId != null">
user_id,
</if>
<if test="bean.nickName != null">
nick_name,
</if>
<if test="bean.email != null">
email,
</if>
<if test="bean.qqOpenId != null">
qq_open_id,
</if>
<if test="bean.qqAvatar != null">
qq_avatar,
</if>
<if test="bean.password != null">
password,
</if>
<if test="bean.joinTime != null">
join_time,
</if>
<if test="bean.lastLoginTime != null">
last_login_time,
</if>
<if test="bean.status != null">
status,
</if>
<if test="bean.useSpace != null">
use_space,
</if>
<if test="bean.totalSpace != null">
total_space,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.userId!=null">
#{bean.userId},
</if>
<if test="bean.nickName!=null">
#{bean.nickName},
</if>
<if test="bean.email!=null">
#{bean.email},
</if>
<if test="bean.qqOpenId!=null">
#{bean.qqOpenId},
</if>
<if test="bean.qqAvatar!=null">
#{bean.qqAvatar},
</if>
<if test="bean.password!=null">
#{bean.password},
</if>
<if test="bean.joinTime!=null">
#{bean.joinTime},
</if>
<if test="bean.lastLoginTime!=null">
#{bean.lastLoginTime},
</if>
<if test="bean.status!=null">
#{bean.status},
</if>
<if test="bean.useSpace!=null">
#{bean.useSpace},
</if>
<if test="bean.totalSpace!=null">
#{bean.totalSpace},
</if>
</trim>
</insert>
<!-- 插入或者更新 (匹配有值的字段)-->
<insert id="insertOrUpdate" parameterType="com.easypan.entity.po.UserInfo">
INSERT INTO user_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="bean.userId != null">
user_id,
</if>
<if test="bean.nickName != null">
nick_name,
</if>
<if test="bean.email != null">
email,
</if>
<if test="bean.qqOpenId != null">
qq_open_id,
</if>
<if test="bean.qqAvatar != null">
qq_avatar,
</if>
<if test="bean.password != null">
password,
</if>
<if test="bean.joinTime != null">
join_time,
</if>
<if test="bean.lastLoginTime != null">
last_login_time,
</if>
<if test="bean.status != null">
status,
</if>
<if test="bean.useSpace != null">
use_space,
</if>
<if test="bean.totalSpace != null">
total_space,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="bean.userId!=null">
#{bean.userId},
</if>
<if test="bean.nickName!=null">
#{bean.nickName},
</if>
<if test="bean.email!=null">
#{bean.email},
</if>
<if test="bean.qqOpenId!=null">
#{bean.qqOpenId},
</if>
<if test="bean.qqAvatar!=null">
#{bean.qqAvatar},
</if>
<if test="bean.password!=null">
#{bean.password},
</if>
<if test="bean.joinTime!=null">
#{bean.joinTime},
</if>
<if test="bean.lastLoginTime!=null">
#{bean.lastLoginTime},
</if>
<if test="bean.status!=null">
#{bean.status},
</if>
<if test="bean.useSpace!=null">
#{bean.useSpace},
</if>
<if test="bean.totalSpace!=null">
#{bean.totalSpace},
</if>
</trim>
on DUPLICATE key update
<trim prefix="" suffix="" suffixOverrides=",">
<if test="bean.userId!=null">
user_id = VALUES(user_id),
</if>
<if test="bean.nickName!=null">
nick_name = VALUES(nick_name),
</if>
<if test="bean.email!=null">
email = VALUES(email),
</if>
<if test="bean.qqOpenId!=null">
qq_open_id = VALUES(qq_open_id),
</if>
<if test="bean.qqAvatar!=null">
qq_avatar = VALUES(qq_avatar),
</if>
<if test="bean.password!=null">
password = VALUES(password),
</if>
<if test="bean.joinTime!=null">
join_time = VALUES(join_time),
</if>
<if test="bean.lastLoginTime!=null">
last_login_time = VALUES(last_login_time),
</if>
<if test="bean.status!=null">
status = VALUES(status),
</if>
<if test="bean.useSpace!=null">
use_space = VALUES(use_space),
</if>
<if test="bean.totalSpace!=null">
total_space = VALUES(total_space),
</if>
</trim>
</insert>
<!-- 添加 (批量插入)-->
<insert id="insertBatch" parameterType="com.easypan.entity.po.UserInfo">
INSERT INTO user_info(
user_id,
nick_name,
email,
qq_open_id,
qq_avatar,
password,
join_time,
last_login_time,
status,
use_space,
total_space
)values
<foreach collection="list" item="item" separator=",">
(
#{item.userId},
#{item.nickName},
#{item.email},
#{item.qqOpenId},
#{item.qqAvatar},
#{item.password},
#{item.joinTime},
#{item.lastLoginTime},
#{item.status},
#{item.useSpace},
#{item.totalSpace}
)
</foreach>
</insert>
<!-- 批量新增修改 (批量插入)-->
<insert id="insertOrUpdateBatch" parameterType="com.easypan.entity.po.UserInfo">
INSERT INTO user_info(
user_id,
nick_name,
email,
qq_open_id,
qq_avatar,
password,
join_time,
last_login_time,
status,
use_space,
total_space
)values
<foreach collection="list" item="item" separator=",">
(
#{item.userId},
#{item.nickName},
#{item.email},
#{item.qqOpenId},
#{item.qqAvatar},
#{item.password},
#{item.joinTime},
#{item.lastLoginTime},
#{item.status},
#{item.useSpace},
#{item.totalSpace}
)
</foreach>
on DUPLICATE key update
user_id = VALUES(user_id),
nick_name = VALUES(nick_name),
email = VALUES(email),
qq_open_id = VALUES(qq_open_id),
qq_avatar = VALUES(qq_avatar),
password = VALUES(password),
join_time = VALUES(join_time),
last_login_time = VALUES(last_login_time),
status = VALUES(status),
use_space = VALUES(use_space),
total_space = VALUES(total_space)
</insert>
<!-- 根据UserId修改-->
<update id="updateByUserId" parameterType="com.easypan.entity.po.UserInfo">
UPDATE user_info
<set>
<if test="bean.nickName != null">
nick_name = #{bean.nickName},
</if>
<if test="bean.email != null">
email = #{bean.email},
</if>
<if test="bean.qqOpenId != null">
qq_open_id = #{bean.qqOpenId},
</if>
<if test="bean.qqAvatar != null">
qq_avatar = #{bean.qqAvatar},
</if>
<if test="bean.password != null">
password = #{bean.password},
</if>
<if test="bean.joinTime != null">
join_time = #{bean.joinTime},
</if>
<if test="bean.lastLoginTime != null">
last_login_time = #{bean.lastLoginTime},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.useSpace != null">
use_space = #{bean.useSpace},
</if>
<if test="bean.totalSpace != null">
total_space = #{bean.totalSpace},
</if>
</set>
where user_id=#{userId}
</update>
<!-- 根据UserId删除-->
<delete id="deleteByUserId">
delete
from user_info
where user_id = #{userId}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByUserId" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from user_info where user_id=#{userId}
</select>
<!-- 根据Email修改-->
<update id="updateByEmail" parameterType="com.easypan.entity.po.UserInfo">
UPDATE user_info
<set>
<if test="bean.userId != null">
user_id = #{bean.userId},
</if>
<if test="bean.nickName != null">
nick_name = #{bean.nickName},
</if>
<if test="bean.qqOpenId != null">
qq_open_id = #{bean.qqOpenId},
</if>
<if test="bean.qqAvatar != null">
qq_avatar = #{bean.qqAvatar},
</if>
<if test="bean.password != null">
password = #{bean.password},
</if>
<if test="bean.joinTime != null">
join_time = #{bean.joinTime},
</if>
<if test="bean.lastLoginTime != null">
last_login_time = #{bean.lastLoginTime},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.useSpace != null">
use_space = #{bean.useSpace},
</if>
<if test="bean.totalSpace != null">
total_space = #{bean.totalSpace},
</if>
</set>
where email=#{email}
</update>
<!-- 根据Email删除-->
<delete id="deleteByEmail">
delete
from user_info
where email = #{email}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByEmail" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from user_info where email=#{email}
</select>
<!-- 根据NickName修改-->
<update id="updateByNickName" parameterType="com.easypan.entity.po.UserInfo">
UPDATE user_info
<set>
<if test="bean.userId != null">
user_id = #{bean.userId},
</if>
<if test="bean.email != null">
email = #{bean.email},
</if>
<if test="bean.qqOpenId != null">
qq_open_id = #{bean.qqOpenId},
</if>
<if test="bean.qqAvatar != null">
qq_avatar = #{bean.qqAvatar},
</if>
<if test="bean.password != null">
password = #{bean.password},
</if>
<if test="bean.joinTime != null">
join_time = #{bean.joinTime},
</if>
<if test="bean.lastLoginTime != null">
last_login_time = #{bean.lastLoginTime},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.useSpace != null">
use_space = #{bean.useSpace},
</if>
<if test="bean.totalSpace != null">
total_space = #{bean.totalSpace},
</if>
</set>
where nick_name=#{nickName}
</update>
<!-- 根据NickName删除-->
<delete id="deleteByNickName">
delete
from user_info
where nick_name = #{nickName}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByNickName" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from user_info where nick_name=#{nickName}
</select>
<!-- 根据QqOpenId修改-->
<update id="updateByQqOpenId" parameterType="com.easypan.entity.po.UserInfo">
UPDATE user_info
<set>
<if test="bean.userId != null">
user_id = #{bean.userId},
</if>
<if test="bean.nickName != null">
nick_name = #{bean.nickName},
</if>
<if test="bean.email != null">
email = #{bean.email},
</if>
<if test="bean.qqAvatar != null">
qq_avatar = #{bean.qqAvatar},
</if>
<if test="bean.password != null">
password = #{bean.password},
</if>
<if test="bean.joinTime != null">
join_time = #{bean.joinTime},
</if>
<if test="bean.lastLoginTime != null">
last_login_time = #{bean.lastLoginTime},
</if>
<if test="bean.status != null">
status = #{bean.status},
</if>
<if test="bean.useSpace != null">
use_space = #{bean.useSpace},
</if>
<if test="bean.totalSpace != null">
total_space = #{bean.totalSpace},
</if>
</set>
where qq_open_id=#{qqOpenId}
</update>
<!-- 根据QqOpenId删除-->
<delete id="deleteByQqOpenId">
delete
from user_info
where qq_open_id = #{qqOpenId}
</delete>
<!-- 根据PrimaryKey获取对象-->
<select id="selectByQqOpenId" resultMap="base_result_map">
select
<include refid="base_column_list"/>
from user_info where qq_open_id=#{qqOpenId}
</select>
<update id="updateUserSpace">
update user_info
<set>
<if test="useSpace != null">
use_space = use_space + #{useSpace},
</if>
<if test="totalSpace != null">
total_space = total_space + #{totalSpace},
</if>
</set>
where user_id = #{userId}
<if test="useSpace != null">
<![CDATA[ and (use_space + #{useSpace}) <= total_space ]]>
</if>
<if test="totalSpace != null">
<![CDATA[ and (total_space + #{totalSpace}) >= use_space ]]>
</if>
</update>
</mapper>
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="10 minutes">
<appender name="stdot" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss,GMT+8} [%p][%c][%M][%L]-> %m%n</pattern>
</layout>
</appender>
<springProperty scope="context" name="log.path" source="project.folder"/>
<springProperty scope="context" name="log.root.level" source="log.root.level"/>
<property name="LOG_FOLDER" value="logs"/>
<property name="LOG_FILE_NAME" value="easypan.log"/>
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/${LOG_FOLDER}/${LOG_FILE_NAME}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${log.path}/${LOG_FOLDER}/${LOG_FILE_NAME}.%d{yyyyMMdd}.%i</FileNamePattern>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>20MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<charset>utf-8</charset>
<pattern>%d{yyyy-MM-dd HH:mm:ss,GMT+8} [%p][%c][%M][%L]-> %m%n</pattern>
</encoder>
<append>false</append>
<prudent>false</prudent>
</appender>
<root level="${log.root.level}">
<appender-ref ref="stdot"/>
<appender-ref ref="file"/>
</root>
</configuration>