first commit
This commit is contained in:
commit
9155cb27a6
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal 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/
|
||||||
106
pom.xml
Normal file
106
pom.xml
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>com.lion</groupId>
|
||||||
|
<artifactId>snss</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>scalable-network-storage-site</name>
|
||||||
|
<description>scalable-network-storage-site</description>
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
|
<version>3.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.30</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-starter-test</artifactId>
|
||||||
|
<version>3.0.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.8.20</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.oshi</groupId>
|
||||||
|
<artifactId>oshi-core</artifactId>
|
||||||
|
<version>6.4.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
<version>1.21</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.lion.snss;
|
||||||
|
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class ScalableNetworkStorageSiteApplication {
|
||||||
|
|
||||||
|
private static ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
context = SpringApplication.run(ScalableNetworkStorageSiteApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void restart() {
|
||||||
|
ApplicationArguments args = context.getBean(ApplicationArguments.class);
|
||||||
|
|
||||||
|
Thread thread = new Thread(() -> {
|
||||||
|
context.close();
|
||||||
|
context = SpringApplication.run(ScalableNetworkStorageSiteApplication.class, args.getSourceArgs());
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.setDaemon(false);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.lion.snss.configuration;
|
||||||
|
|
||||||
|
import com.lion.snss.interceptor.Interceptor;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebComponentConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
Interceptor interceptor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
|
registry.addMapping("/**")
|
||||||
|
.allowCredentials(true)
|
||||||
|
.allowedOriginPatterns("*")
|
||||||
|
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||||
|
.allowedHeaders("*")
|
||||||
|
.exposedHeaders("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(interceptor).excludePathPatterns("/getFileByShareCode/**");
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/main/java/com/lion/snss/controller/FileController.java
Normal file
32
src/main/java/com/lion/snss/controller/FileController.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package com.lion.snss.controller;
|
||||||
|
|
||||||
|
import com.lion.snss.service.FileService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/file")
|
||||||
|
public class FileController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
FileService fileService;
|
||||||
|
|
||||||
|
@GetMapping("/getFile/**")
|
||||||
|
public void getFile(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String path, String sessionId){
|
||||||
|
fileService.getFile(httpRequest, httpResponse, path, sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(path="/upload/**")
|
||||||
|
public String uploadFile(HttpServletRequest request, MultipartFile file, String sessionId){
|
||||||
|
String url = request.getRequestURL().toString();
|
||||||
|
String[] temp = url.split("/upload/");
|
||||||
|
System.out.println("上传文件:" + file.getOriginalFilename());
|
||||||
|
if(temp.length == 1)
|
||||||
|
return fileService.uploadFile("", file, sessionId);
|
||||||
|
else
|
||||||
|
return fileService.uploadFile(temp[1], file, sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/java/com/lion/snss/controller/IndexController.java
Normal file
19
src/main/java/com/lion/snss/controller/IndexController.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.lion.snss.controller;
|
||||||
|
|
||||||
|
import com.lion.snss.service.FileService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class IndexController {
|
||||||
|
@Resource
|
||||||
|
FileService fileService;
|
||||||
|
|
||||||
|
@GetMapping("/getFileByShareCode/**")
|
||||||
|
public void getFileByShareCode(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String shareCode){
|
||||||
|
fileService.getFileByShareCode(httpRequest, httpResponse, shareCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.lion.snss.dao;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
import org.apache.ibatis.annotations.Update;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CustomConfigurationMapper {
|
||||||
|
String PATH = "path";
|
||||||
|
String IP = "ip";
|
||||||
|
|
||||||
|
String DOMAIN = "domain";
|
||||||
|
|
||||||
|
String IS_AUTH = "is_auth";
|
||||||
|
|
||||||
|
String ID = "id";
|
||||||
|
|
||||||
|
String REVERSE_PROXY_PREFIX = "reverse_proxy_prefix";
|
||||||
|
|
||||||
|
String TOTAL_SPACE = "total_space";
|
||||||
|
|
||||||
|
String AVAILABLE_SPACE = "available_space";
|
||||||
|
|
||||||
|
|
||||||
|
@Select("select value from custom_configuration where key=#{key}")
|
||||||
|
String selectValue(String key);
|
||||||
|
|
||||||
|
@Update("update custom_configuration set value=#{value} where key=#{key}")
|
||||||
|
void updateValue(@Param("key") String key, @Param("value") String value);
|
||||||
|
}
|
||||||
59
src/main/java/com/lion/snss/dao/ShareFileMapper.java
Normal file
59
src/main/java/com/lion/snss/dao/ShareFileMapper.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package com.lion.snss.dao;
|
||||||
|
|
||||||
|
import com.lion.snss.pojo.ShareFileDownloadRecord;
|
||||||
|
import com.lion.snss.pojo.ShareFile;
|
||||||
|
import org.apache.ibatis.annotations.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ShareFileMapper {
|
||||||
|
|
||||||
|
@Insert("insert into share_file (share_code, file_path, expire_time, available_count, total_count, sharer) " +
|
||||||
|
"values (#{shareCode}, #{filePath}, #{expireTime}, #{availableCount}, #{totalCount}, #{sharer})")
|
||||||
|
void insertShareFilePojo(ShareFile shareFile);
|
||||||
|
|
||||||
|
@Select("select * from share_file where share_code=#{shareCode}")
|
||||||
|
ShareFile selectShareFileByShareCode(String shareCode);
|
||||||
|
|
||||||
|
@Select("select * from share_file where file_path=#{filePath}")
|
||||||
|
ShareFile selectShareFileByFilePath(String filePath);
|
||||||
|
|
||||||
|
@Select("select * from share_file where file_path like '%' || #{filePath} || '%'")
|
||||||
|
ArrayList<ShareFile> selectShareFilesByFilePath(String filePath);
|
||||||
|
|
||||||
|
@Select("select share_code from share_file where file_path=#{filePath}")
|
||||||
|
String selectShareCodeByFilePath(String filePath);
|
||||||
|
|
||||||
|
|
||||||
|
@Delete("delete from share_file where share_code=#{shareCode}")
|
||||||
|
void deleteShareFile(String shareCode);
|
||||||
|
|
||||||
|
@Delete("delete from share_file")
|
||||||
|
void deleteAllShareFile();
|
||||||
|
|
||||||
|
@Select("select * from share_file")
|
||||||
|
ShareFile[] selectAllShareFile();
|
||||||
|
|
||||||
|
@Select("select * from share_file where sharer=#{userid}")
|
||||||
|
ShareFile[] selectAllShareFileByUserid(int userid);
|
||||||
|
|
||||||
|
@Update("update share_file set expire_time=#{expireTime}, available_count=#{availableCount}, total_count=#{totalCount} " +
|
||||||
|
"where share_code = #{shareCode}")
|
||||||
|
void updateShareFile(ShareFile shareFile);
|
||||||
|
|
||||||
|
@Insert("insert into share_file_download_record values (#{shareCode}, #{ip}, #{time}, #{ua})")
|
||||||
|
void insertShareFileRecord(@Param("shareCode") String shareCode, @Param("ip") String ip, @Param("time") long time, @Param("ua") String ua);
|
||||||
|
|
||||||
|
@Select("select count(*) from share_file_download_record where share_code=#{shareCode} and ip=#{ip}")
|
||||||
|
int selectShareFileRecordAmount(@Param("shareCode") String shareCode, @Param("ip") String ip);
|
||||||
|
|
||||||
|
@Select("select * from share_file_download_record where share_code=#{shareCode}")
|
||||||
|
ShareFileDownloadRecord[] selectDownloadRecord(@Param("shareCode") String shareCode);
|
||||||
|
|
||||||
|
@Delete("delete from share_file_download_record where share_code=#{shareCode}")
|
||||||
|
void deleteShareFileRecord(String shareCode);
|
||||||
|
|
||||||
|
@Delete("delete from share_file_download_record")
|
||||||
|
void deleteAllShareFileRecord();
|
||||||
|
}
|
||||||
44
src/main/java/com/lion/snss/interceptor/Interceptor.java
Normal file
44
src/main/java/com/lion/snss/interceptor/Interceptor.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package com.lion.snss.interceptor;
|
||||||
|
|
||||||
|
import com.lion.snss.pojo.User;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Interceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
public HashMap<String, User> sessionId2user;
|
||||||
|
public Interceptor(){
|
||||||
|
sessionId2user = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
|
||||||
|
String sessionId = request.getParameter("sessionId");
|
||||||
|
return sessionId != null && sessionId2user.containsKey(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUsers(HashMap<String, User> users){
|
||||||
|
this.sessionId2user.clear();
|
||||||
|
this.sessionId2user.putAll(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUser(Map.Entry<String, User> entry){
|
||||||
|
sessionId2user.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public User removeUser(String sessionId){
|
||||||
|
return sessionId2user.remove(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertAdminUser(String sessionId){
|
||||||
|
User user = new User();
|
||||||
|
user.setId(1);
|
||||||
|
sessionId2user.put(sessionId, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/main/java/com/lion/snss/message/AbstractMessage.java
Normal file
32
src/main/java/com/lion/snss/message/AbstractMessage.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AbstractMessage {
|
||||||
|
public static final int FILE_QUERY_MESSAGE = 1;
|
||||||
|
public static final int FILE_RESPONSE_MESSAGE = 2;
|
||||||
|
public static final int STATUS_MESSAGE = 10;
|
||||||
|
public static final int MOVE_FILE_REQUEST_MESSAGE = 15;
|
||||||
|
public static final int MOVE_FILE_RESPONSE_MESSAGE = 16;
|
||||||
|
public static final int PAIR_MESSAGE = 20;
|
||||||
|
public static final int PAIR_RESULT_MESSAGE = 21;
|
||||||
|
public static final int UN_PAIR_MESSAGE = 22;
|
||||||
|
public static final int DYNAMIC_CONFIG_MESSAGE = 30;
|
||||||
|
public static final int RESPONSE_MESSAGE = 40;
|
||||||
|
public static final int TASK_STATUS_MESSAGE = 50;
|
||||||
|
public static final int TASK_CANCEL_MESSAGE = 51;
|
||||||
|
public static final int COMPRESS_FILE_MESSAGE = 60;
|
||||||
|
public static final int FILE_OPERATE_MESSAGE = 61;
|
||||||
|
public static final int EXTRACT_FILE_MESSAGE = 62;
|
||||||
|
public static final int SHARE_FILE_MESSAGE = 70;
|
||||||
|
public static final int ADJUST_SHARE_MESSAGE = 71;
|
||||||
|
public static final int CANCEL_SHARE_MESSAGE = 72;
|
||||||
|
public static final int SHARE_FILE_QUERY_MESSAGE = 73;
|
||||||
|
public static final int CONFIG_MESSAGE = 80;
|
||||||
|
public static final int CONNECT_MESSAGE = 90;
|
||||||
|
|
||||||
|
public int messageType;
|
||||||
|
public int messageId;
|
||||||
|
}
|
||||||
14
src/main/java/com/lion/snss/message/AdjustShareMessage.java
Normal file
14
src/main/java/com/lion/snss/message/AdjustShareMessage.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AdjustShareMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = ADJUST_SHARE_MESSAGE;
|
||||||
|
}
|
||||||
|
String shareCode;
|
||||||
|
Integer time;
|
||||||
|
Integer count;
|
||||||
|
int userid;
|
||||||
|
}
|
||||||
12
src/main/java/com/lion/snss/message/CancelShareMessage.java
Normal file
12
src/main/java/com/lion/snss/message/CancelShareMessage.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CancelShareMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = CANCEL_SHARE_MESSAGE;
|
||||||
|
}
|
||||||
|
String shareCode;
|
||||||
|
int userid;
|
||||||
|
}
|
||||||
15
src/main/java/com/lion/snss/message/CompressFileMessage.java
Normal file
15
src/main/java/com/lion/snss/message/CompressFileMessage.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CompressFileMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = COMPRESS_FILE_MESSAGE;
|
||||||
|
}
|
||||||
|
String targetPath;
|
||||||
|
String relativePath;
|
||||||
|
String[] paths;
|
||||||
|
int taskId;
|
||||||
|
int userid;
|
||||||
|
}
|
||||||
31
src/main/java/com/lion/snss/message/ConfigMessage.java
Normal file
31
src/main/java/com/lion/snss/message/ConfigMessage.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ConfigMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = CONFIG_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static byte MOVE_SITE_STORAGE_PATH = 1;
|
||||||
|
public final static byte MOVE_USER_STORAGE_PATH = 2;
|
||||||
|
public final static byte VERIFY_USER_SPACE = 3;
|
||||||
|
|
||||||
|
int operate;
|
||||||
|
String oldPath;
|
||||||
|
String newPath;
|
||||||
|
String path;
|
||||||
|
|
||||||
|
public void moveSitePath(String oldPath, String newPath){
|
||||||
|
this.oldPath = oldPath;
|
||||||
|
this.newPath = newPath;
|
||||||
|
operate = MOVE_SITE_STORAGE_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveUserPath(String oldPath, String newPath){
|
||||||
|
this.oldPath = oldPath;
|
||||||
|
this.newPath = newPath;
|
||||||
|
operate = MOVE_USER_STORAGE_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main/java/com/lion/snss/message/ConnectMessage.java
Normal file
10
src/main/java/com/lion/snss/message/ConnectMessage.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ConnectMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = CONNECT_MESSAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import com.lion.snss.pojo.User;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DynamicConfigMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = DYNAMIC_CONFIG_MESSAGE;
|
||||||
|
}
|
||||||
|
public static final byte ALL = 0;
|
||||||
|
public static final byte ADD_IP = 1;
|
||||||
|
public static final byte REMOVE_IP = 2;
|
||||||
|
public static final byte ADD_USER = 3;
|
||||||
|
public static final byte REMOVE_USER = 4;
|
||||||
|
public static final byte UPDATE_USER_STORAGE = 5;
|
||||||
|
|
||||||
|
byte operate;
|
||||||
|
Map.Entry<Integer, String> ip;
|
||||||
|
Map.Entry<String, User> user;
|
||||||
|
|
||||||
|
public void updateUserStorage(User user){
|
||||||
|
this.user = new AbstractMap.SimpleEntry<>(null, user);
|
||||||
|
operate = UPDATE_USER_STORAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<Integer, String> ips;
|
||||||
|
HashMap<String, User> users;
|
||||||
|
}
|
||||||
15
src/main/java/com/lion/snss/message/ExtractFileMessage.java
Normal file
15
src/main/java/com/lion/snss/message/ExtractFileMessage.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ExtractFileMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = EXTRACT_FILE_MESSAGE;
|
||||||
|
}
|
||||||
|
String relativePath;
|
||||||
|
String sourcePath;
|
||||||
|
String targetPath;
|
||||||
|
int taskId;
|
||||||
|
int userid;
|
||||||
|
}
|
||||||
22
src/main/java/com/lion/snss/message/FileOperateMessage.java
Normal file
22
src/main/java/com/lion/snss/message/FileOperateMessage.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FileOperateMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = FILE_OPERATE_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//新建
|
||||||
|
//删除
|
||||||
|
//重命名
|
||||||
|
public final static int CREATE = 1;
|
||||||
|
public final static int DELETE = 2;
|
||||||
|
public final static int RENAME = 3;
|
||||||
|
int operate;
|
||||||
|
int userid;
|
||||||
|
String[] paths;
|
||||||
|
String name;
|
||||||
|
String path;
|
||||||
|
}
|
||||||
13
src/main/java/com/lion/snss/message/FileQueryMessage.java
Normal file
13
src/main/java/com/lion/snss/message/FileQueryMessage.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FileQueryMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = FILE_QUERY_MESSAGE;
|
||||||
|
}
|
||||||
|
String path;
|
||||||
|
String relativePath; //相对路径,用于去除多余的路径
|
||||||
|
int userid;
|
||||||
|
}
|
||||||
15
src/main/java/com/lion/snss/message/FileResponseMessage.java
Normal file
15
src/main/java/com/lion/snss/message/FileResponseMessage.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import com.lion.snss.pojo.FileNode;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FileResponseMessage extends AbstractMessage {
|
||||||
|
{
|
||||||
|
messageType = FILE_RESPONSE_MESSAGE;
|
||||||
|
}
|
||||||
|
List<FileNode> files;
|
||||||
|
String data;
|
||||||
|
}
|
||||||
64
src/main/java/com/lion/snss/message/MessageCodec.java
Normal file
64
src/main/java/com/lion/snss/message/MessageCodec.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.ByteToMessageCodec;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class MessageCodec extends ByteToMessageCodec<AbstractMessage> {
|
||||||
|
ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
|
||||||
|
public MessageCodec(){
|
||||||
|
objectMapper = new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void encode(ChannelHandlerContext channelHandlerContext, AbstractMessage abstractMessage, ByteBuf byteBuf) throws Exception {
|
||||||
|
byte[] bytes = objectMapper.writeValueAsBytes(abstractMessage);
|
||||||
|
|
||||||
|
byteBuf.writeInt(abstractMessage.messageType);
|
||||||
|
byteBuf.writeInt(bytes.length);
|
||||||
|
byteBuf.writeBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
|
||||||
|
int type = byteBuf.readInt();
|
||||||
|
int length = byteBuf.readInt();
|
||||||
|
AbstractMessage abstractMessage;
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
byteBuf.readBytes(bytes);
|
||||||
|
abstractMessage = switch (type){
|
||||||
|
case AbstractMessage.FILE_QUERY_MESSAGE -> objectMapper.readValue(bytes, FileQueryMessage.class);
|
||||||
|
case AbstractMessage.FILE_RESPONSE_MESSAGE -> objectMapper.readValue(bytes, FileResponseMessage.class);
|
||||||
|
case AbstractMessage.STATUS_MESSAGE -> objectMapper.readValue(bytes, StatusMessage.class);
|
||||||
|
case AbstractMessage.MOVE_FILE_REQUEST_MESSAGE -> objectMapper.readValue(bytes, MoveFileRequestMessage.class);
|
||||||
|
case AbstractMessage.MOVE_FILE_RESPONSE_MESSAGE -> objectMapper.readValue(bytes, MoveFileResponseMessage.class);
|
||||||
|
case AbstractMessage.PAIR_MESSAGE -> objectMapper.readValue(bytes, PairMessage.class);
|
||||||
|
case AbstractMessage.PAIR_RESULT_MESSAGE -> objectMapper.readValue(bytes, PairResultMessage.class);
|
||||||
|
case AbstractMessage.UN_PAIR_MESSAGE -> objectMapper.readValue(bytes, UnPairMessage.class);
|
||||||
|
case AbstractMessage.DYNAMIC_CONFIG_MESSAGE -> objectMapper.readValue(bytes, DynamicConfigMessage.class);
|
||||||
|
case AbstractMessage.RESPONSE_MESSAGE -> objectMapper.readValue(bytes, ResponseMessage.class);
|
||||||
|
case AbstractMessage.TASK_STATUS_MESSAGE -> objectMapper.readValue(bytes, TaskStatusMessage.class);
|
||||||
|
case AbstractMessage.TASK_CANCEL_MESSAGE -> objectMapper.readValue(bytes, TaskCancelMessage.class);
|
||||||
|
case AbstractMessage.COMPRESS_FILE_MESSAGE -> objectMapper.readValue(bytes, CompressFileMessage.class);
|
||||||
|
case AbstractMessage.FILE_OPERATE_MESSAGE -> objectMapper.readValue(bytes, FileOperateMessage.class);
|
||||||
|
case AbstractMessage.EXTRACT_FILE_MESSAGE -> objectMapper.readValue(bytes, ExtractFileMessage.class);
|
||||||
|
case AbstractMessage.SHARE_FILE_MESSAGE -> objectMapper.readValue(bytes, ShareFileMessage.class);
|
||||||
|
case AbstractMessage.ADJUST_SHARE_MESSAGE -> objectMapper.readValue(bytes, AdjustShareMessage.class);
|
||||||
|
case AbstractMessage.CANCEL_SHARE_MESSAGE -> objectMapper.readValue(bytes, CancelShareMessage.class);
|
||||||
|
case AbstractMessage.SHARE_FILE_QUERY_MESSAGE -> objectMapper.readValue(bytes, ShareFileQueryMessage.class);
|
||||||
|
case AbstractMessage.CONFIG_MESSAGE -> objectMapper.readValue(bytes, ConfigMessage.class);
|
||||||
|
case AbstractMessage.CONNECT_MESSAGE -> objectMapper.readValue(bytes, ConnectMessage.class);
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: " + type);
|
||||||
|
};
|
||||||
|
|
||||||
|
list.add(abstractMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 四种情况
|
||||||
|
* 1.主服务器发送到子服务器
|
||||||
|
* 2.子服务器发送到主服务器
|
||||||
|
* 3.子服务器发送到子服务器
|
||||||
|
* 4.子服务器发送到其他子服务器
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MoveFileRequestMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = MOVE_FILE_REQUEST_MESSAGE;
|
||||||
|
}
|
||||||
|
int userid;
|
||||||
|
int sender;
|
||||||
|
int receiver;
|
||||||
|
int port;
|
||||||
|
//起始id, 如果是多个文件,则每个文件的任务id为起始id+index
|
||||||
|
int taskId;
|
||||||
|
boolean isDelete;
|
||||||
|
long fileSize;
|
||||||
|
String targetPath;
|
||||||
|
String[] fileNames;
|
||||||
|
String sourcePath;
|
||||||
|
String fileName;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MoveFileResponseMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = MOVE_FILE_RESPONSE_MESSAGE;
|
||||||
|
}
|
||||||
|
boolean result;
|
||||||
|
String cause;
|
||||||
|
int taskId;
|
||||||
|
}
|
||||||
21
src/main/java/com/lion/snss/message/PairMessage.java
Normal file
21
src/main/java/com/lion/snss/message/PairMessage.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PairMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = PAIR_MESSAGE;
|
||||||
|
}
|
||||||
|
String ip;
|
||||||
|
String domain;
|
||||||
|
String reverseProxyPrefix;
|
||||||
|
String hostname;
|
||||||
|
String system;
|
||||||
|
String cpuArch;
|
||||||
|
String cpuName;
|
||||||
|
int cpuCore;
|
||||||
|
int cpuThread;
|
||||||
|
String storagePath;
|
||||||
|
long availableSpace;
|
||||||
|
}
|
||||||
17
src/main/java/com/lion/snss/message/PairResultMessage.java
Normal file
17
src/main/java/com/lion/snss/message/PairResultMessage.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PairResultMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = PAIR_RESULT_MESSAGE;
|
||||||
|
}
|
||||||
|
int id; //分配的id -1为拒绝
|
||||||
|
HashMap<Integer, String> ips; //当前连接的所有服务器ip以及id
|
||||||
|
String sessionId; //管理员的sessionId
|
||||||
|
long totalSpace; //服务器总共可分配的容量
|
||||||
|
}
|
||||||
69
src/main/java/com/lion/snss/message/ResponseMessage.java
Normal file
69
src/main/java/com/lion/snss/message/ResponseMessage.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ResponseMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = RESPONSE_MESSAGE;
|
||||||
|
}
|
||||||
|
boolean result;
|
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
HashMap<String, String> data;
|
||||||
|
|
||||||
|
public ResponseMessage(){
|
||||||
|
data = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseMessage(int messageId){
|
||||||
|
this.messageId = messageId;
|
||||||
|
data = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataAndResult(String data, boolean result){
|
||||||
|
this.result = result;
|
||||||
|
if(result){
|
||||||
|
this.data.put("data", data);
|
||||||
|
}else{
|
||||||
|
this.data.put("cause", data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String key, String value){
|
||||||
|
data.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String key, Object o){
|
||||||
|
data.put(key, String.valueOf(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String key){
|
||||||
|
return data.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseMessage success(String data) {
|
||||||
|
this.data.put("data", data);
|
||||||
|
result = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseMessage success(Object o){
|
||||||
|
success(String.valueOf(o));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseMessage success(){
|
||||||
|
result = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseMessage failure(String cause){
|
||||||
|
this.data.put("cause", cause);
|
||||||
|
result = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/java/com/lion/snss/message/ShareFileMessage.java
Normal file
15
src/main/java/com/lion/snss/message/ShareFileMessage.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ShareFileMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = SHARE_FILE_MESSAGE;
|
||||||
|
}
|
||||||
|
String path;
|
||||||
|
Integer count;
|
||||||
|
Integer time;
|
||||||
|
String[] fileNames;
|
||||||
|
int userid;
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ShareFileQueryMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = SHARE_FILE_QUERY_MESSAGE;
|
||||||
|
}
|
||||||
|
public final static byte QUERY_SHARE_FILE = 1;
|
||||||
|
public final static byte QUERY_SHARE_FILES = 2;
|
||||||
|
|
||||||
|
byte operate;
|
||||||
|
int userid;
|
||||||
|
String username;
|
||||||
|
String relativePath;
|
||||||
|
String shareCode;
|
||||||
|
}
|
||||||
25
src/main/java/com/lion/snss/message/StatusMessage.java
Normal file
25
src/main/java/com/lion/snss/message/StatusMessage.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class StatusMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = STATUS_MESSAGE;
|
||||||
|
}
|
||||||
|
int id;
|
||||||
|
long usedMemory;
|
||||||
|
long totalMemory;
|
||||||
|
double usedMemoryPercentage;
|
||||||
|
long usedSpace;
|
||||||
|
long totalSpace;
|
||||||
|
double usedSpacePercentage;
|
||||||
|
double[] systemLoad;
|
||||||
|
double usedCpuPercentage;
|
||||||
|
long ioRead;
|
||||||
|
long ioWrite;
|
||||||
|
long networkReceive;
|
||||||
|
long networkSend;
|
||||||
|
long systemUpTime;
|
||||||
|
long systemBootTime;
|
||||||
|
}
|
||||||
11
src/main/java/com/lion/snss/message/TaskCancelMessage.java
Normal file
11
src/main/java/com/lion/snss/message/TaskCancelMessage.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TaskCancelMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = TASK_CANCEL_MESSAGE;
|
||||||
|
}
|
||||||
|
int[] taskIds;
|
||||||
|
}
|
||||||
14
src/main/java/com/lion/snss/message/TaskStatusMessage.java
Normal file
14
src/main/java/com/lion/snss/message/TaskStatusMessage.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import com.lion.snss.pojo.Task;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TaskStatusMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = TASK_STATUS_MESSAGE;
|
||||||
|
}
|
||||||
|
Set<Task> tasks;
|
||||||
|
}
|
||||||
10
src/main/java/com/lion/snss/message/UnPairMessage.java
Normal file
10
src/main/java/com/lion/snss/message/UnPairMessage.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package com.lion.snss.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UnPairMessage extends AbstractMessage{
|
||||||
|
{
|
||||||
|
messageType = UN_PAIR_MESSAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/main/java/com/lion/snss/message/lombok.config
Normal file
2
src/main/java/com/lion/snss/message/lombok.config
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
config.stopBubbling=true
|
||||||
|
lombok.equalsAndHashCode.callSuper=call
|
||||||
25
src/main/java/com/lion/snss/pojo/FileNode.java
Normal file
25
src/main/java/com/lion/snss/pojo/FileNode.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package com.lion.snss.pojo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FileNode {
|
||||||
|
public static String FOLDER = "FOLDER";
|
||||||
|
public static String FILE = "FILE";
|
||||||
|
String name;
|
||||||
|
String path;
|
||||||
|
String type;
|
||||||
|
long size;
|
||||||
|
long lastModify;
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
String shareCode;
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
Date expireTime;
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
|
||||||
|
Integer totalCount;
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
|
||||||
|
Integer availableCount;
|
||||||
|
}
|
||||||
23
src/main/java/com/lion/snss/pojo/ShareFile.java
Normal file
23
src/main/java/com/lion/snss/pojo/ShareFile.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.lion.snss.pojo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
|
||||||
|
public class ShareFile {
|
||||||
|
String shareCode; //分享码
|
||||||
|
String filePath; //文件路径
|
||||||
|
Date expireTime; //过期时间
|
||||||
|
int availableCount; //剩余可下载次数
|
||||||
|
int totalCount; //总共下载次数
|
||||||
|
int sharer; //分享者id
|
||||||
|
String username; //分享者
|
||||||
|
|
||||||
|
@JsonProperty("downloadRecords")
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
ShareFileDownloadRecord[] shareFileDownloadRecords;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.lion.snss.pojo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ShareFileDownloadRecord {
|
||||||
|
String shareCode;
|
||||||
|
String ip;
|
||||||
|
long time;
|
||||||
|
String ua;
|
||||||
|
}
|
||||||
119
src/main/java/com/lion/snss/pojo/Task.java
Normal file
119
src/main/java/com/lion/snss/pojo/Task.java
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package com.lion.snss.pojo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
//打包 传输
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Task {
|
||||||
|
public static final String COMPRESS = "compress";
|
||||||
|
public static final String TRANSFER = "transfer";
|
||||||
|
public static final String EXTRACT = "extract";
|
||||||
|
|
||||||
|
int userid; //提交的用户
|
||||||
|
int siteId; //进行任务的服务器id
|
||||||
|
String type; //compress || transfer
|
||||||
|
String status; //waiting proceeding success failure
|
||||||
|
boolean complete; //是否完成
|
||||||
|
boolean local; //是否为本地
|
||||||
|
|
||||||
|
//转移
|
||||||
|
String sourcePath;
|
||||||
|
String targetPath;
|
||||||
|
String filename;
|
||||||
|
boolean delete;
|
||||||
|
int receiver;
|
||||||
|
int sender;
|
||||||
|
|
||||||
|
//打包
|
||||||
|
String[] paths;
|
||||||
|
String relativePath;
|
||||||
|
|
||||||
|
//转移
|
||||||
|
public Task(int taskId, int userid, long total, boolean isDelete, String sourcePath, String targetPath, String filename, int receiver, int sender){
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.userid = userid;
|
||||||
|
this.siteId = sender;
|
||||||
|
|
||||||
|
this.sourcePath = sourcePath;
|
||||||
|
this.targetPath = targetPath;
|
||||||
|
this.delete = isDelete;
|
||||||
|
this.receiver = receiver;
|
||||||
|
this.sender = sender;
|
||||||
|
this.filename = filename;
|
||||||
|
this.total = total;
|
||||||
|
|
||||||
|
|
||||||
|
local = false;
|
||||||
|
complete = false;
|
||||||
|
status = "waiting";
|
||||||
|
type = TRANSFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//打包
|
||||||
|
public Task(int taskId, int userid, String filename, int siteId, long total, String targetPath, String[] paths, String relativePath){
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.userid = userid;
|
||||||
|
this.siteId = siteId;
|
||||||
|
|
||||||
|
this.total = total;
|
||||||
|
this.targetPath = targetPath;
|
||||||
|
this.paths = paths;
|
||||||
|
this.relativePath = relativePath;
|
||||||
|
this.filename = filename;
|
||||||
|
|
||||||
|
local = false;
|
||||||
|
complete = false;
|
||||||
|
status = "waiting";
|
||||||
|
type = COMPRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//解包
|
||||||
|
public Task(int taskId, int userid, String filename, int sideId, long total, String sourcePath, String targetPath, String relativePath){
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.userid = userid;
|
||||||
|
this.siteId = sideId;
|
||||||
|
|
||||||
|
this.total = total;
|
||||||
|
this.sourcePath = sourcePath;
|
||||||
|
this.targetPath = targetPath;
|
||||||
|
this.relativePath = relativePath;
|
||||||
|
this.filename = filename;
|
||||||
|
|
||||||
|
local = false;
|
||||||
|
complete = false;
|
||||||
|
status = "waiting";
|
||||||
|
type = EXTRACT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isSuccess(){
|
||||||
|
return status.equals("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
String cause; //失败原因
|
||||||
|
|
||||||
|
int taskId;
|
||||||
|
double percentage;
|
||||||
|
long speed;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
AtomicLong proceed;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
AtomicLong last;
|
||||||
|
|
||||||
|
long total;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean isProceeding(){
|
||||||
|
return status.equals("proceeding");
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/main/java/com/lion/snss/pojo/User.java
Normal file
14
src/main/java/com/lion/snss/pojo/User.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.lion.snss.pojo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class User {
|
||||||
|
int id;
|
||||||
|
String username;
|
||||||
|
String passcode; //加盐md5
|
||||||
|
long availableSpace;
|
||||||
|
long totalSpace;
|
||||||
|
String storagePath; //path
|
||||||
|
int siteId;
|
||||||
|
}
|
||||||
1247
src/main/java/com/lion/snss/service/CommunicateToMainService.java
Normal file
1247
src/main/java/com/lion/snss/service/CommunicateToMainService.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,136 @@
|
|||||||
|
package com.lion.snss.service;
|
||||||
|
|
||||||
|
import com.lion.snss.dao.CustomConfigurationMapper;
|
||||||
|
import com.lion.snss.message.FileOperateMessage;
|
||||||
|
import com.lion.snss.message.MessageCodec;
|
||||||
|
import com.lion.snss.message.MoveFileRequestMessage;
|
||||||
|
import com.lion.snss.message.ResponseMessage;
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.*;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||||
|
import io.netty.handler.logging.LogLevel;
|
||||||
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class CommunicateToSiteService {
|
||||||
|
|
||||||
|
String storagePath;
|
||||||
|
|
||||||
|
ExecutorService threadPool;
|
||||||
|
|
||||||
|
public CommunicateToSiteService(CustomConfigurationMapper customConfigurationMapper){
|
||||||
|
storagePath = customConfigurationMapper.selectValue(CustomConfigurationMapper.PATH);
|
||||||
|
threadPool = Executors.newFixedThreadPool(4);
|
||||||
|
new ServerBootstrap().channel(NioServerSocketChannel.class)
|
||||||
|
.group(new NioEventLoopGroup())
|
||||||
|
.childHandler(new ChannelInitializer<NioSocketChannel>() {
|
||||||
|
@Override
|
||||||
|
protected void initChannel(NioSocketChannel ch) {
|
||||||
|
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(10000000, 4, 4));
|
||||||
|
ch.pipeline().addLast(new MessageCodec());
|
||||||
|
ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
|
||||||
|
ch.pipeline().addLast(new MyChannelInBoundHandlerAdapter());
|
||||||
|
}
|
||||||
|
}).bind(9999);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receiveFile(MoveFileRequestMessage moveFileRequestMessage, String address, Channel channel){
|
||||||
|
File targetFile = new File(storagePath + moveFileRequestMessage.getTargetPath(), moveFileRequestMessage.getFileName());
|
||||||
|
ResponseMessage response = new ResponseMessage(moveFileRequestMessage.getMessageId());
|
||||||
|
log.info(address);
|
||||||
|
File[] roots = File.listRoots();
|
||||||
|
long freeSpace = 1000000000;
|
||||||
|
for (File root : roots)
|
||||||
|
if(targetFile.getPath().startsWith(root.getPath())){
|
||||||
|
freeSpace = root.getFreeSpace();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(targetFile.exists()) {
|
||||||
|
channel.writeAndFlush(response.failure("文件已存在")).sync();
|
||||||
|
return;
|
||||||
|
} else if(!targetFile.getParentFile().isDirectory()) {
|
||||||
|
channel.writeAndFlush(response.failure("此路径文件夹不存在")).sync();
|
||||||
|
return;
|
||||||
|
} else if (freeSpace < moveFileRequestMessage.getFileSize()) {
|
||||||
|
channel.writeAndFlush(response.failure("磁盘空间已满")).sync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
channel.writeAndFlush(response.success()).sync();
|
||||||
|
Thread.sleep(200);
|
||||||
|
}catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
threadPool.submit(() -> {
|
||||||
|
File tempFile = new File(targetFile.getPath() + "...undone");
|
||||||
|
try(FileOutputStream fileOutputStream = new FileOutputStream(targetFile);
|
||||||
|
Socket socket = new Socket()) {
|
||||||
|
socket.connect(new InetSocketAddress(address, moveFileRequestMessage.getPort()));
|
||||||
|
InputStream inputStream = socket.getInputStream();
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
int len;
|
||||||
|
long received = 0;
|
||||||
|
CRC32 crc32 = new CRC32();
|
||||||
|
while((len = inputStream.read(buf)) != -1){
|
||||||
|
fileOutputStream.write(buf, 0, len);
|
||||||
|
crc32.update(buf, 0, len);
|
||||||
|
received += len;
|
||||||
|
}
|
||||||
|
fileOutputStream.close();
|
||||||
|
inputStream.close();
|
||||||
|
socket.close();
|
||||||
|
if(received != moveFileRequestMessage.getFileSize()){
|
||||||
|
tempFile.delete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Thread.sleep(500);
|
||||||
|
if(tempFile.renameTo(targetFile) || targetFile.exists()) {
|
||||||
|
response.success("文件接收成功");
|
||||||
|
response.put("crc32", String.valueOf(crc32.getValue()));
|
||||||
|
} else {
|
||||||
|
response.failure("文件接收失败:重命名失败");
|
||||||
|
tempFile.delete();
|
||||||
|
}
|
||||||
|
}catch (IOException| InterruptedException e){
|
||||||
|
log.error(e.getMessage());
|
||||||
|
response.failure("文件接收失败:" + e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if(tempFile.exists())
|
||||||
|
tempFile.delete();
|
||||||
|
channel.writeAndFlush(response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyChannelInBoundHandlerAdapter extends ChannelInboundHandlerAdapter{
|
||||||
|
@Override
|
||||||
|
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||||
|
if(msg instanceof MoveFileRequestMessage moveFileRequestMessage){
|
||||||
|
log.info(ctx.channel().remoteAddress().toString());
|
||||||
|
threadPool.submit(() -> receiveFile(moveFileRequestMessage, ctx.channel().remoteAddress().toString().split(":")[0].replace("/", ""), ctx.channel()));
|
||||||
|
}else if(msg instanceof FileOperateMessage fileOperateMessage){ //仅删除文件
|
||||||
|
File file = new File(storagePath + fileOperateMessage.getPath());
|
||||||
|
if(fileOperateMessage.getOperate() == FileOperateMessage.DELETE)
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
201
src/main/java/com/lion/snss/service/FileService.java
Normal file
201
src/main/java/com/lion/snss/service/FileService.java
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
package com.lion.snss.service;
|
||||||
|
|
||||||
|
import com.lion.snss.dao.CustomConfigurationMapper;
|
||||||
|
import com.lion.snss.dao.ShareFileMapper;
|
||||||
|
import com.lion.snss.interceptor.Interceptor;
|
||||||
|
import com.lion.snss.message.DynamicConfigMessage;
|
||||||
|
import com.lion.snss.pojo.ShareFile;
|
||||||
|
import com.lion.snss.pojo.User;
|
||||||
|
import com.lion.snss.util.IoUtil;
|
||||||
|
import com.lion.snss.util.Response;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class FileService {
|
||||||
|
String storagePath;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
ShareFileMapper shareFileMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
CommunicateToMainService communicateToMainService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
Interceptor interceptor;
|
||||||
|
|
||||||
|
HashMap<String, Long> ipAndShareCode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public FileService(CustomConfigurationMapper customConfigurationMapper){
|
||||||
|
storagePath = customConfigurationMapper.selectValue(CustomConfigurationMapper.PATH);
|
||||||
|
ipAndShareCode = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getFileByShareCode(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String shareCode){
|
||||||
|
if(shareCode == null)
|
||||||
|
try {
|
||||||
|
httpResponse.sendError(404, "ShareCode invalid");
|
||||||
|
return;
|
||||||
|
} catch (IOException e) {throw new RuntimeException(e);}
|
||||||
|
|
||||||
|
ShareFile shareFile = shareFileMapper.selectShareFileByShareCode(shareCode);
|
||||||
|
if (shareFile == null)
|
||||||
|
try{
|
||||||
|
httpResponse.sendError(404, "ShareCode is not exist");
|
||||||
|
return;
|
||||||
|
}catch (IOException e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String ip;
|
||||||
|
if(httpRequest.getRemoteAddr().equals("127.0.0.1")) {
|
||||||
|
ip = httpRequest.getHeader("X-Forwarded-For");
|
||||||
|
if(ip == null)
|
||||||
|
ip = "127.0.0.1";
|
||||||
|
if(ip.contains(","))
|
||||||
|
ip = ip.split(",")[0].trim();
|
||||||
|
if(ip.contains(":"))
|
||||||
|
ip = ip.split(":")[0].trim();
|
||||||
|
} else
|
||||||
|
ip = httpRequest.getRemoteAddr();
|
||||||
|
|
||||||
|
String ua = httpRequest.getHeader("User-Agent");
|
||||||
|
if(ua == null)
|
||||||
|
try {
|
||||||
|
httpResponse.sendError(404, "User-Agent invalid");
|
||||||
|
return;
|
||||||
|
} catch (IOException e) {throw new RuntimeException(e);}
|
||||||
|
else if(ua.length() > 255)
|
||||||
|
ua = ua.substring(0, 255);
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
//如果是有限次数分享,则判断当前ip是否下载过,如果未下载过,则将可用次数-1
|
||||||
|
if (shareFile.getTotalCount() != 0 && shareFileMapper.selectShareFileRecordAmount(shareCode, ip) == 0) {
|
||||||
|
if(shareFile.getAvailableCount() > 0) {
|
||||||
|
shareFile.setAvailableCount(shareFile.getAvailableCount() - 1);
|
||||||
|
shareFileMapper.updateShareFile(shareFile);
|
||||||
|
}else{
|
||||||
|
try {
|
||||||
|
httpResponse.sendError(404, "ShareCode download count exceed");
|
||||||
|
} catch (IOException e) {throw new RuntimeException(e);}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果是有限时间分享
|
||||||
|
if(shareFile.getExpireTime() != null) {
|
||||||
|
Calendar ExpireTime = Calendar.getInstance();
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
|
||||||
|
ExpireTime.setTime(shareFile.getExpireTime());
|
||||||
|
//判断是否超过分享时间
|
||||||
|
if (ExpireTime.before(now)) {
|
||||||
|
try {
|
||||||
|
httpResponse.sendError(404, "ShareCode is expired or File is not exist");
|
||||||
|
return;
|
||||||
|
} catch (IOException e) {throw new RuntimeException(e);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断文件是否存在
|
||||||
|
if(!new File(shareFile.getFilePath()).isFile()){
|
||||||
|
try {
|
||||||
|
httpResponse.sendError(404, "File is not exist");
|
||||||
|
return;
|
||||||
|
} catch (IOException e) {throw new RuntimeException(e);}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ipAndShareCode为下载ip+shareCode,如果包含的话,则说明这个ip不是第一次下载这个文件了
|
||||||
|
if(ipAndShareCode.containsKey(ip+shareCode)) {
|
||||||
|
long before = ipAndShareCode.get(ip+shareCode);
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
//30分钟内多次下载不记录,对于支持多线程下载的下载器来说,如果每次下载都记录,则会产生大量下载记录
|
||||||
|
if(now - before > 1000 * 1800) { //1800秒
|
||||||
|
ipAndShareCode.put(ip+shareCode, now);
|
||||||
|
shareFileMapper.insertShareFileRecord(shareCode, ip, System.currentTimeMillis(), ua);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
shareFileMapper.insertShareFileRecord(shareCode, ip, System.currentTimeMillis(), ua);
|
||||||
|
ipAndShareCode.put(ip+shareCode, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IoUtil.export(httpRequest, httpResponse, shareFile.getFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getFile(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String path, String sessionId){
|
||||||
|
User user = interceptor.sessionId2user.get(sessionId);
|
||||||
|
if(user.getId() != 1)
|
||||||
|
path = user.getStoragePath() + path;
|
||||||
|
|
||||||
|
File file = new File(storagePath, path);
|
||||||
|
if(file.isFile())
|
||||||
|
IoUtil.export(httpRequest, httpResponse, file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String uploadFile(String path, MultipartFile file, String sessionId) {
|
||||||
|
Response response = Response.generateResponse();
|
||||||
|
if(path == null || file == null){
|
||||||
|
response.failure("参数不完整");
|
||||||
|
return response.toJSONString();
|
||||||
|
}
|
||||||
|
if(path.contains("%"))
|
||||||
|
path = URLDecoder.decode(path, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
User user = interceptor.sessionId2user.get(sessionId);
|
||||||
|
if(user.getId() != 1) {
|
||||||
|
if(user.getAvailableSpace() < file.getSize())
|
||||||
|
return response.failure("当前空间不足").toJSONString();
|
||||||
|
else
|
||||||
|
user.setAvailableSpace(user.getAvailableSpace() - file.getSize());
|
||||||
|
|
||||||
|
path = user.getStoragePath() + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("上传文件:{}, 目标路径:{}", file.getName(), path);
|
||||||
|
File directory = new File(storagePath, path);
|
||||||
|
if(directory.isDirectory()){
|
||||||
|
File targetFile = new File(storagePath + path, Objects.requireNonNull(file.getOriginalFilename()));
|
||||||
|
|
||||||
|
if(targetFile.exists())
|
||||||
|
return response.failure("目标文件已存在").toJSONString();
|
||||||
|
else
|
||||||
|
try {
|
||||||
|
file.transferTo(Path.of(storagePath, path, Objects.requireNonNull(file.getOriginalFilename())));
|
||||||
|
} catch (IOException e) {
|
||||||
|
response.failure("上传失败");
|
||||||
|
log.error(e.getMessage());
|
||||||
|
//上传失败 返还空间
|
||||||
|
user.setAvailableSpace(user.getAvailableSpace() + file.getSize());
|
||||||
|
Path.of(storagePath, path, Objects.requireNonNull(file.getOriginalFilename())).toFile().delete();
|
||||||
|
} finally {
|
||||||
|
if(user.getId() != 1) {
|
||||||
|
DynamicConfigMessage dynamicConfigMessage = new DynamicConfigMessage();
|
||||||
|
dynamicConfigMessage.updateUserStorage(user);
|
||||||
|
communicateToMainService.sendMessageToMain(dynamicConfigMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.success("上传成功");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
response.failure("该路径不存在或者不是文件夹");
|
||||||
|
|
||||||
|
return response.toJSONString();
|
||||||
|
}
|
||||||
|
}
|
||||||
113
src/main/java/com/lion/snss/service/TaskService.java
Normal file
113
src/main/java/com/lion/snss/service/TaskService.java
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package com.lion.snss.service;
|
||||||
|
|
||||||
|
import com.lion.snss.pojo.Task;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TaskService {
|
||||||
|
@Getter
|
||||||
|
ConcurrentHashMap<Integer, Task> tasks;
|
||||||
|
|
||||||
|
ScheduledExecutorService thread;
|
||||||
|
|
||||||
|
ReentrantLock lock;
|
||||||
|
|
||||||
|
public TaskService(){
|
||||||
|
tasks = new ConcurrentHashMap<>();
|
||||||
|
lock = new ReentrantLock();
|
||||||
|
thread = Executors.newScheduledThreadPool(1);
|
||||||
|
thread.scheduleAtFixedRate(this::calculateProgress, 0, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculateProgress(){
|
||||||
|
Set<Integer> taskIds = tasks.keySet();
|
||||||
|
|
||||||
|
for(Integer taskId: taskIds){
|
||||||
|
Task task = tasks.get(taskId);
|
||||||
|
|
||||||
|
if(task.isComplete() || !task.isProceeding())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(task.getProceed().get() == -1) {
|
||||||
|
tasks.remove(taskId);
|
||||||
|
taskIds.remove(task.getTaskId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
task.setSpeed(task.getProceed().get() - task.getLast().get());
|
||||||
|
task.getLast().set(task.getProceed().get());
|
||||||
|
task.setPercentage(((double) task.getProceed().get() / task.getTotal()) * 100);
|
||||||
|
|
||||||
|
if(task.getProceed().get() == task.getTotal()) {
|
||||||
|
task.setPercentage(100);
|
||||||
|
task.setComplete(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void submitTask(Task task){
|
||||||
|
tasks.put(task.getTaskId(), task);
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断工作线程是否结束:当所有本地任务未进行时,即工作线程结束
|
||||||
|
public boolean isThreadStop(){
|
||||||
|
lock.lock();
|
||||||
|
for (Task task : tasks.values())
|
||||||
|
if(task.isProceeding()) {
|
||||||
|
lock.unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getWaitingTask(){
|
||||||
|
for (Task task : tasks.values())
|
||||||
|
if(task.getStatus().equals("waiting"))
|
||||||
|
return task;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTask(int id){
|
||||||
|
Task task;
|
||||||
|
if((task = tasks.remove(id)) != null)
|
||||||
|
task.getProceed().set(-10086);
|
||||||
|
}
|
||||||
|
public void removeTasks(int[] ids){
|
||||||
|
for (int id : ids)
|
||||||
|
removeTask(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void failure(int taskId, String cause){
|
||||||
|
Task task = tasks.get(taskId);
|
||||||
|
if(task != null) {
|
||||||
|
task.setStatus("failure");
|
||||||
|
task.setCause(cause);
|
||||||
|
task.setComplete(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void success(int taskId){
|
||||||
|
if(tasks.containsKey(taskId)) {
|
||||||
|
tasks.get(taskId).setStatus("success");
|
||||||
|
tasks.get(taskId).setComplete(true);
|
||||||
|
tasks.get(taskId).setPercentage(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeComplete(){
|
||||||
|
tasks.forEach((k, v) -> {
|
||||||
|
if(v.getStatus().equals("success") || v.getStatus().equals("failure"))
|
||||||
|
tasks.remove(k);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/main/java/com/lion/snss/util/CustomUtil.java
Normal file
72
src/main/java/com/lion/snss/util/CustomUtil.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package com.lion.snss.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CustomUtil {
|
||||||
|
|
||||||
|
public static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 寻找一定数量的可用端口
|
||||||
|
*
|
||||||
|
* @return 可用端口的起始位置 -1为没有(几乎没有可能)
|
||||||
|
*/
|
||||||
|
public static short findIdlePort(){
|
||||||
|
for(int i=20000; i<65535; i++){
|
||||||
|
try(ServerSocket ignored = new ServerSocket(i)){
|
||||||
|
return (short) i;
|
||||||
|
}catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long calculateFilesSize(String directory, String[] files){
|
||||||
|
AtomicLong size = new AtomicLong();
|
||||||
|
|
||||||
|
for (String filename : files) {
|
||||||
|
File file = new File(directory, filename);
|
||||||
|
if(file.isDirectory())
|
||||||
|
size.addAndGet(calculateDirectorySize(file.getPath()));
|
||||||
|
else
|
||||||
|
size.addAndGet(file.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
return size.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long calculateDirectorySize(String path){
|
||||||
|
AtomicLong size = new AtomicLong();
|
||||||
|
File file = new File(path);
|
||||||
|
|
||||||
|
if(!file.isDirectory())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.walkFileTree(file.toPath(), new SimpleFileVisitor<>() {
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||||
|
size.addAndGet(file.toFile().length());
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}catch (IOException e){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
270
src/main/java/com/lion/snss/util/IoUtil.java
Normal file
270
src/main/java/com/lion/snss/util/IoUtil.java
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
package com.lion.snss.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.net.NetUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.core.util.URLUtil;
|
||||||
|
import cn.hutool.system.SystemUtil;
|
||||||
|
import cn.hutool.system.oshi.CpuInfo;
|
||||||
|
import cn.hutool.system.oshi.OshiUtil;
|
||||||
|
import com.lion.snss.message.StatusMessage;
|
||||||
|
import com.lion.snss.message.PairMessage;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.catalina.connector.ClientAbortException;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import oshi.hardware.CentralProcessor;
|
||||||
|
import oshi.hardware.GlobalMemory;
|
||||||
|
import oshi.hardware.HWDiskStore;
|
||||||
|
import oshi.hardware.NetworkIF;
|
||||||
|
import oshi.software.os.OperatingSystem;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Slf4j
|
||||||
|
public class IoUtil {
|
||||||
|
static long ioRead;
|
||||||
|
static long ioWrite;
|
||||||
|
static long networkSend;
|
||||||
|
static long networkReceive;
|
||||||
|
static NetworkIF networkIF;
|
||||||
|
static List<HWDiskStore> diskStores;
|
||||||
|
static CpuInfo cpuInfo;
|
||||||
|
static GlobalMemory globalMemory;
|
||||||
|
|
||||||
|
static long send;
|
||||||
|
static long sendNow;
|
||||||
|
static long receive;
|
||||||
|
static long receiveNow;
|
||||||
|
|
||||||
|
static long read;
|
||||||
|
static long readNow;
|
||||||
|
static long write;
|
||||||
|
static long writeNow;
|
||||||
|
|
||||||
|
static {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init(){
|
||||||
|
ScheduledExecutorService thread = Executors.newScheduledThreadPool(1);
|
||||||
|
List<NetworkIF> networkIFs = OshiUtil.getNetworkIFs();
|
||||||
|
cpuInfo = OshiUtil.getCpuInfo();
|
||||||
|
globalMemory = OshiUtil.getMemory();
|
||||||
|
|
||||||
|
for (NetworkIF nif : networkIFs) {
|
||||||
|
if (SystemUtil.getOsInfo().isLinux()) {
|
||||||
|
if (nif.getName().equals("eth0") || nif.getName().equals("ens33"))
|
||||||
|
networkIF = nif;
|
||||||
|
} else if (nif.getName().equals("eth4") || nif.getName().equals("ethernet_32769"))
|
||||||
|
networkIF = nif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(networkIF == null)
|
||||||
|
log.error("网卡 eth0 不存在");
|
||||||
|
else{
|
||||||
|
send = networkIF.getBytesSent();
|
||||||
|
receive = networkIF.getBytesRecv();
|
||||||
|
}
|
||||||
|
|
||||||
|
diskStores = OshiUtil.getDiskStores();
|
||||||
|
for (HWDiskStore diskStore : diskStores) {
|
||||||
|
read += diskStore.getReadBytes();
|
||||||
|
write += diskStore.getWriteBytes();
|
||||||
|
}
|
||||||
|
thread.scheduleAtFixedRate(IoUtil::monitor, 0, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void monitor(){
|
||||||
|
networkIF.updateAttributes();
|
||||||
|
sendNow = networkIF.getBytesSent();
|
||||||
|
receiveNow = networkIF.getBytesRecv();
|
||||||
|
networkSend = sendNow - send;
|
||||||
|
networkReceive = receiveNow - receive;
|
||||||
|
send = sendNow;
|
||||||
|
receive = receiveNow;
|
||||||
|
|
||||||
|
writeNow = 0;
|
||||||
|
readNow = 0;
|
||||||
|
for (HWDiskStore diskStore : diskStores) {
|
||||||
|
diskStore.updateAttributes();
|
||||||
|
writeNow += diskStore.getWriteBytes();
|
||||||
|
readNow += diskStore.getReadBytes();
|
||||||
|
}
|
||||||
|
ioWrite = writeNow - write;
|
||||||
|
ioRead = readNow - read;
|
||||||
|
write = writeNow;
|
||||||
|
read = readNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static PairMessage generatePairMessage(){
|
||||||
|
PairMessage pairMessage = new PairMessage();
|
||||||
|
pairMessage.setIp(networkIF.getIPv4addr()[0].split("/")[0]);
|
||||||
|
pairMessage.setHostname(NetUtil.getLocalHostName());
|
||||||
|
|
||||||
|
OperatingSystem os = OshiUtil.getOs();
|
||||||
|
pairMessage.setSystem(os.getFamily() + " " + os.getVersionInfo().toString());
|
||||||
|
pairMessage.setCpuArch(System.getProperty("os.arch"));
|
||||||
|
|
||||||
|
CentralProcessor processor = OshiUtil.getHardware().getProcessor();
|
||||||
|
pairMessage.setCpuName(processor.getProcessorIdentifier().getName().strip());
|
||||||
|
pairMessage.setCpuCore(processor.getPhysicalProcessorCount());
|
||||||
|
pairMessage.setCpuThread(processor.getLogicalProcessorCount());
|
||||||
|
return pairMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StatusMessage generateStatusMessage(int id, String path){
|
||||||
|
StatusMessage statusMessage = new StatusMessage();
|
||||||
|
statusMessage.setId(id);
|
||||||
|
|
||||||
|
statusMessage.setTotalMemory(globalMemory.getTotal());
|
||||||
|
statusMessage.setUsedMemory(globalMemory.getTotal() - globalMemory.getAvailable());
|
||||||
|
statusMessage.setUsedMemoryPercentage(numberFormat((double) statusMessage.getUsedMemory() / statusMessage.getTotalMemory()));
|
||||||
|
|
||||||
|
File file = new File(path);
|
||||||
|
statusMessage.setTotalSpace(file.getTotalSpace());
|
||||||
|
statusMessage.setUsedSpace(file.getTotalSpace() - file.getFreeSpace());
|
||||||
|
statusMessage.setUsedSpacePercentage(numberFormat((double) statusMessage.getUsedSpace() / statusMessage.getTotalSpace()));
|
||||||
|
|
||||||
|
statusMessage.setSystemLoad(OshiUtil.getHardware().getProcessor().getSystemLoadAverage(3));
|
||||||
|
statusMessage.setUsedCpuPercentage(numberFormat(100 - OshiUtil.getCpuInfo().getFree()));
|
||||||
|
|
||||||
|
statusMessage.setIoRead(ioRead);
|
||||||
|
statusMessage.setIoWrite(ioWrite);
|
||||||
|
statusMessage.setNetworkReceive(networkReceive);
|
||||||
|
statusMessage.setNetworkSend(networkSend);
|
||||||
|
|
||||||
|
statusMessage.setSystemUpTime(OshiUtil.getOs().getSystemUptime());
|
||||||
|
statusMessage.setSystemBootTime(OshiUtil.getOs().getSystemBootTime());
|
||||||
|
|
||||||
|
return statusMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double numberFormat(double number){
|
||||||
|
if(number <= 0)
|
||||||
|
return number;
|
||||||
|
if(number < 1)
|
||||||
|
return Double.parseDouble(String.format("%.1f", number * 100));
|
||||||
|
else
|
||||||
|
return Double.parseDouble(String.format("%.1f", number));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void export(HttpServletRequest request, HttpServletResponse response, String path) {
|
||||||
|
File file = new File(path);
|
||||||
|
|
||||||
|
String fileName = file.getName();
|
||||||
|
|
||||||
|
String range = request.getHeader(HttpHeaders.RANGE);
|
||||||
|
|
||||||
|
String rangeSeparator = "-";
|
||||||
|
// 开始下载位置
|
||||||
|
long startByte = 0;
|
||||||
|
// 结束下载位置
|
||||||
|
long endByte = file.length() - 1;
|
||||||
|
|
||||||
|
// 如果是断点续传
|
||||||
|
if (range != null && range.contains("bytes=") && range.contains(rangeSeparator)) {
|
||||||
|
// 设置响应状态码为 206
|
||||||
|
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
||||||
|
|
||||||
|
range = range.substring(range.lastIndexOf("=") + 1).trim();
|
||||||
|
String[] ranges = range.split(rangeSeparator);
|
||||||
|
try {
|
||||||
|
// 判断 range 的类型
|
||||||
|
if (ranges.length == 1) {
|
||||||
|
// 类型一:bytes=-2343
|
||||||
|
if (range.startsWith(rangeSeparator)) {
|
||||||
|
endByte = Long.parseLong(ranges[0]);
|
||||||
|
}
|
||||||
|
// 类型二:bytes=2343-
|
||||||
|
else if (range.endsWith(rangeSeparator)) {
|
||||||
|
startByte = Long.parseLong(ranges[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 类型三:bytes=22-2343
|
||||||
|
else if (ranges.length == 2) {
|
||||||
|
startByte = Long.parseLong(ranges[0]);
|
||||||
|
endByte = Long.parseLong(ranges[1]);
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 传参不规范,则直接返回所有内容
|
||||||
|
startByte = 0;
|
||||||
|
endByte = file.length() - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有 ranges 即全部一次性传输,需要用 200 状态码,这一行应该可以省掉,因为默认返回是 200 状态码
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
//要下载的长度(endByte 为总长度 -1,这时候要加回去)
|
||||||
|
long contentLength = endByte - startByte + 1;
|
||||||
|
//文件类型
|
||||||
|
String contentType = request.getServletContext().getMimeType(fileName);
|
||||||
|
|
||||||
|
if (StrUtil.isEmpty(contentType)) {
|
||||||
|
contentType = "attachment";
|
||||||
|
}
|
||||||
|
|
||||||
|
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
|
||||||
|
// 这里文件名换你想要的,inline 表示浏览器可以直接使用
|
||||||
|
// 参考资料:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, contentType + ";filename=\"" + URLUtil.encode(fileName) + "\"");
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
|
||||||
|
// [要下载的开始位置]-[结束位置]/[文件总大小]
|
||||||
|
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + startByte + rangeSeparator + endByte + "/" + file.length());
|
||||||
|
|
||||||
|
BufferedOutputStream outputStream;
|
||||||
|
RandomAccessFile randomAccessFile = null;
|
||||||
|
//已传送数据大小
|
||||||
|
long transmitted = 0;
|
||||||
|
try {
|
||||||
|
randomAccessFile = new RandomAccessFile(file, "r");
|
||||||
|
outputStream = new BufferedOutputStream(response.getOutputStream());
|
||||||
|
byte[] buff = new byte[4096];
|
||||||
|
int len = 0;
|
||||||
|
randomAccessFile.seek(startByte);
|
||||||
|
while ((transmitted + len) <= contentLength && (len = randomAccessFile.read(buff)) != -1) {
|
||||||
|
outputStream.write(buff, 0, len);
|
||||||
|
transmitted += len;
|
||||||
|
// 本地测试, 防止下载速度过快
|
||||||
|
// Thread.sleep(1);
|
||||||
|
}
|
||||||
|
// 处理不足 buff.length 部分
|
||||||
|
if (transmitted < contentLength) {
|
||||||
|
len = randomAccessFile.read(buff, 0, (int) (contentLength - transmitted));
|
||||||
|
outputStream.write(buff, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.flush();
|
||||||
|
response.flushBuffer();
|
||||||
|
randomAccessFile.close();
|
||||||
|
// log.trace("下载完毕: {}-{}, 已传输 {}", startByte, endByte, transmitted);
|
||||||
|
} catch (ClientAbortException e) {
|
||||||
|
// ignore 用户停止下载
|
||||||
|
// log.trace("用户停止下载: {}-{}, 已传输 {}", startByte, endByte, transmitted);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (randomAccessFile != null) {
|
||||||
|
randomAccessFile.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/main/java/com/lion/snss/util/Response.java
Normal file
87
src/main/java/com/lion/snss/util/Response.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package com.lion.snss.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
public class Response {
|
||||||
|
ObjectNode result;
|
||||||
|
public Response(){
|
||||||
|
result = CustomUtil.objectMapper.createObjectNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response generateResponse(){
|
||||||
|
return new Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(String key, String value){
|
||||||
|
result.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(String key){
|
||||||
|
return result.get(key).asText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data){
|
||||||
|
result.put("data", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(String result){
|
||||||
|
this.result.put("result", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void success(){
|
||||||
|
setResult("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void success(String result){
|
||||||
|
success();
|
||||||
|
setData(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void failure(){
|
||||||
|
setResult("failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response failure(String result){
|
||||||
|
failure();
|
||||||
|
setData(result);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResult(){
|
||||||
|
return result.get("data").asText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess(){
|
||||||
|
return result.get("result").asText().equals("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String _failure(String result){
|
||||||
|
Response response = generateResponse();
|
||||||
|
response.failure(result);
|
||||||
|
return response.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String _success(String result){
|
||||||
|
Response response = generateResponse();
|
||||||
|
response.success(result);
|
||||||
|
return response.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String _success(){
|
||||||
|
Response response = generateResponse();
|
||||||
|
response.success();
|
||||||
|
return response.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String _default(){
|
||||||
|
Response response = Response.generateResponse();
|
||||||
|
response.failure("参数错误");
|
||||||
|
|
||||||
|
return response.toJSONString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSONString(){
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/resources/application.yaml
Normal file
26
src/main/resources/application.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driver-class-name: org.sqlite.JDBC
|
||||||
|
url: jdbc:sqlite:snss.db
|
||||||
|
# url: jdbc:sqlite:D:\WorkSpace\code\Java\scalable-network-storage-site\src\main\resources\snss.db
|
||||||
|
mvc:
|
||||||
|
view:
|
||||||
|
prefix: /resource/templates/
|
||||||
|
suffix: .html
|
||||||
|
|
||||||
|
thymeleaf:
|
||||||
|
check-template-location: false
|
||||||
|
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 10000MB
|
||||||
|
max-request-size: 10000MB
|
||||||
|
enabled: true
|
||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
error:
|
||||||
|
include-message: always
|
||||||
|
|
||||||
|
mybatis:
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
BIN
src/main/resources/snss-empty.db
Normal file
BIN
src/main/resources/snss-empty.db
Normal file
Binary file not shown.
BIN
src/main/resources/snss.db
Normal file
BIN
src/main/resources/snss.db
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user