5 Commits

Author SHA1 Message Date
2d93f70704 Merge remote-tracking branch 'origin/develop' 2025-07-25 17:09:34 +08:00
40f07bdd6e Merge remote-tracking branch 'origin/develop' 2025-07-25 14:35:11 +08:00
3b6c8bedf6 Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	README.md
2025-07-25 09:30:36 +08:00
1931697a87 !1 Update README.md
Merge pull request !1 from gitee-agent/N/A
2025-07-24 15:39:24 +00:00
gitee-bot
b882e85134 Update README.md 2025-07-24 15:35:16 +00:00
10 changed files with 136 additions and 180 deletions

152
README.md
View File

@@ -1,77 +1,77 @@
# fmt
## 介绍
`fmt` 是一个基于 Spring Boot 的文件管理工具,旨在提供便捷的文件上传、下载、打包、删除等操作。它结合了简洁的前端界面与强大的后端功能,适用于需要进行文件管理的各类应用场景。
## 软件架构
本项目采用前后端一体化架构,后端基于 Spring Boot 框架,使用 Java 语言开发,前端采用 HTML、CSS 和 JavaScript 技术,结合 `axui` 框架进行界面渲染。主要模块包括:
- **文件上传模块**:支持文件上传并保存至服务器。
- **文件下载模块**:支持文件下载及 ZIP 打包下载。
- **文件管理模块**:支持文件删除、批量删除等操作。
- **日志模块**:实时推送日志信息。
- **WebSocket 模块**:用于前后端实时通信。
- **工具类模块**:包括 MD5 工具、操作系统工具等。
## 安装教程
1. **克隆项目**
```bash
git clone https://gitee.com/thzxx/fmt.git
```
2. **构建项目**
使用 Maven 构建项目:
```bash
cd fmt
mvn clean package
```
3. **运行项目**
启动 Spring Boot 应用:
```bash
java -jar target/fmt.jar
```
4. **访问项目**
打开浏览器访问:
```
http://localhost:8080
```
## 使用说明
- **上传文件**
访问 `/upload/index` 页面,选择文件进行上传。
- **下载文件**
访问 `/download/index` 页面,点击文件进行下载,或使用 `/download/file` 接口下载指定路径文件。
- **打包下载**
使用 `/download/packZip` 接口,传入文件名列表进行 ZIP 打包下载。
- **删除文件**
使用 `/download/delete` 或 `/download/batchDel` 接口进行单个或批量删除。
- **查看日志**
访问 `/logging/index` 页面,实时查看日志信息。
- **WebSocket 实时通信**
前端通过 WebSocket 连接 `/ws`,接收服务器推送的消息。
## 参与贡献
欢迎贡献代码和改进项目。请遵循以下步骤:
1. Fork 项目。
2. 创建新分支。
3. 提交代码。
4. 创建 Pull Request。
如发现 Bug 或有改进建议,请提交 Issue 或直接联系项目维护者。
## 许可证
# fmt
## 介绍
`fmt` 是一个基于 Spring Boot 的文件管理工具,旨在提供便捷的文件上传、下载、打包、删除等操作。它结合了简洁的前端界面与强大的后端功能,适用于需要进行文件管理的各类应用场景。
## 软件架构
本项目采用前后端一体化架构,后端基于 Spring Boot 框架,使用 Java 语言开发,前端采用 HTML、CSS 和 JavaScript 技术,结合 `axui` 框架进行界面渲染。主要模块包括:
- **文件上传模块**:支持文件上传并保存至服务器。
- **文件下载模块**:支持文件下载及 ZIP 打包下载。
- **文件管理模块**:支持文件删除、批量删除等操作。
- **日志模块**:实时推送日志信息。
- **WebSocket 模块**:用于前后端实时通信。
- **工具类模块**:包括 MD5 工具、操作系统工具等。
## 安装教程
1. **克隆项目**
```bash
git clone https://gitee.com/thzxx/fmt.git
```
2. **构建项目**
使用 Maven 构建项目:
```bash
cd fmt
mvn clean package
```
3. **运行项目**
启动 Spring Boot 应用:
```bash
java -jar target/fmt.jar
```
4. **访问项目**
打开浏览器访问:
```
http://localhost:8080
```
## 使用说明
- **上传文件**
访问 `/upload/index` 页面,选择文件进行上传。
- **下载文件**
访问 `/download/index` 页面,点击文件进行下载,或使用 `/download/file` 接口下载指定路径文件。
- **打包下载**
使用 `/download/packZip` 接口,传入文件名列表进行 ZIP 打包下载。
- **删除文件**
使用 `/download/delete` 或 `/download/batchDel` 接口进行单个或批量删除。
- **查看日志**
访问 `/logging/index` 页面,实时查看日志信息。
- **WebSocket 实时通信**
前端通过 WebSocket 连接 `/ws`,接收服务器推送的消息。
## 参与贡献
欢迎贡献代码和改进项目。请遵循以下步骤:
1. Fork 项目。
2. 创建新分支。
3. 提交代码。
4. 创建 Pull Request。
如发现 Bug 或有改进建议,请提交 Issue 或直接联系项目维护者。
## 许可证
本项目采用 MIT 许可证。详情请查看项目根目录下的 `LICENSE` 文件。

View File

@@ -10,7 +10,7 @@
</parent>
<groupId>cn.somkit</groupId>
<artifactId>fmt</artifactId>
<version>2.1.3</version>
<version>2.1.2</version>
<name>fmt</name>
<description>File Manage System for by SpringBoot</description>
<properties>

View File

@@ -1,9 +1,6 @@
package cn.somkit.fmt.action;
import cn.hutool.json.JSONUtil;
import cn.somkit.fmt.utils.OsInfoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -34,8 +31,6 @@ import java.util.zip.ZipOutputStream;
@RequestMapping("/download")
public class DownloadAction {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${somkit.upload.path.windows}")
private String windows_path;
@@ -46,7 +41,6 @@ public class DownloadAction {
public ModelAndView index(String keyboard) throws Exception{
String path = OsInfoUtil.isWindows() ? windows_path :
OsInfoUtil.isLinux() ? linux_path : null;
logger.info("获取文件存储路径:{}", path);
assert path != null;
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
@@ -65,7 +59,6 @@ public class DownloadAction {
list = list.stream().filter(map -> String.valueOf(map.get("filename"))
.contains(keyboard)).collect(Collectors.toList());
}
logger.info("关键词:{},文件数量:{}", keyboard, list.size());
ModelAndView mv = new ModelAndView();
mv.setViewName("download");
mv.addObject("files", list);
@@ -73,7 +66,7 @@ public class DownloadAction {
return mv;
}
private Map<String, Object> getObjectMap(File file) {
private static Map<String, Object> getObjectMap(File file) {
BigDecimal filesize = BigDecimal.valueOf(file.length())
.divide(BigDecimal.valueOf(1024 * 1024), 2, RoundingMode.HALF_UP);
Long time = file.lastModified();
@@ -84,7 +77,6 @@ public class DownloadAction {
map.put("filepath", file.getAbsolutePath());
map.put("filesize", filesize);
map.put("filetime", filetime);
logger.info("文件信息:{}", JSONUtil.toJsonStr(map));
return map;
}
@@ -110,7 +102,6 @@ public class DownloadAction {
}
outputStream.flush();
} catch (IOException e) {
logger.error("IO错误", e);
throw new RuntimeException("IO错误: " + e.getMessage());
} finally {
// 尝试在流关闭后删除文件
@@ -120,7 +111,7 @@ public class DownloadAction {
}
} catch (IOException e) {
// 记录日志或采取其他措施
logger.error("删除文件失败{}", e.getMessage());
System.err.println("删除文件失败: " + e.getMessage());
}
}
};

View File

@@ -1,35 +0,0 @@
package cn.somkit.fmt.config;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.metona.mq.MQToolkit;
import cn.metona.mq.core.MessageQueue;
import cn.somkit.fmt.entity.LoggerMessage;
import java.time.Instant;
import java.time.ZoneId;
public class LogMonitorAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
private static final String Queue_Name = "log-monitor";
@Override
protected void append(ILoggingEvent event) {
LoggerMessage msg = new LoggerMessage(
event.getLevel().toString(),
event.getThreadName(),
event.getLoggerName(),
event.getFormattedMessage(),
DateUtil.format(Instant.ofEpochMilli(event.getTimeStamp()).atZone(ZoneId.systemDefault()).toLocalDateTime(),
"yyyy-MM-dd HH:mm:ss.SSS"),
ProcessHandle.current().pid()
);
//发送日志信息到日志监控队列
MessageQueue.QueueStats queueStats = MQToolkit.getQueueStats(Queue_Name);
if(queueStats != null && queueStats.isRunning() && !queueStats.isPaused()){
MQToolkit.sendMessage(Queue_Name, "log.monitor", JSONUtil.toJsonStr(msg));
}
}
}

View File

@@ -1,25 +0,0 @@
package cn.somkit.fmt.config;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class LogbackConfigListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
// 配置logback
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
// 添加自定义appender
LogMonitorAppender appender = new LogMonitorAppender();
appender.setContext(loggerContext);
appender.start();
rootLogger.addAppender(appender);
}
}

View File

@@ -2,19 +2,15 @@ package cn.somkit.fmt.entity;
public class LoggerMessage {
String level;
String threadName;
String name;
String message;
String timestamp;
long number;
public LoggerMessage(String level, String threadName, String loggerName, String message, String timestamp, long number) {
public LoggerMessage(String level, String loggerName, String message, String timestamp) {
this.level = level;
this.threadName = threadName;
this.name = loggerName;
this.message = message;
this.timestamp = timestamp;
this.number = number;
}
public String getLevel() {
@@ -25,14 +21,6 @@ public class LoggerMessage {
this.level = level;
}
public String getThreadName() {
return threadName;
}
public void setThreadName(String threadName) {
this.threadName = threadName;
}
public String getName() {
return name;
}
@@ -56,12 +44,4 @@ public class LoggerMessage {
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
}

View File

@@ -0,0 +1,52 @@
package cn.somkit.fmt.filter;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.metona.mq.MQToolkit;
import cn.metona.mq.core.MessageQueue;
import cn.somkit.fmt.entity.LoggerMessage;
import java.time.Instant;
import java.time.ZoneId;
public class LogStashFilter extends Filter<ILoggingEvent> {
private static final String Queue_Name = "log-monitor";
Level level;
public LogStashFilter() {
}
@Override
public FilterReply decide(ILoggingEvent e) {
LoggerMessage msg = new LoggerMessage(
e.getLevel().toString(),
e.getLoggerName(),
e.getFormattedMessage(),
DateUtil.format(Instant.ofEpochMilli(e.getTimeStamp()).atZone(ZoneId.systemDefault()).toLocalDateTime(),
"yyyy-MM-dd HH:mm:ss.SSS")
);
//发送日志信息到日志监控队列
MessageQueue.QueueStats queueStats = MQToolkit.getQueueStats(Queue_Name);
if(queueStats != null && queueStats.isRunning() && !queueStats.isPaused()){
MQToolkit.sendMessage(Queue_Name, "log.monitor", JSONUtil.toJsonStr(msg));
}
return FilterReply.NEUTRAL;
}
public void setLevel(String level) {
this.level = Level.toLevel(level);
}
public void start() {
if (this.level != null) {
super.start();
}
}
}

View File

@@ -5,8 +5,8 @@
<!-- 日志输出到控制台 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
<filter class="cn.somkit.fmt.filter.LogStashFilter">
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
@@ -15,7 +15,7 @@
</appender>
<!-- 指定日志输出级别以及启动的Appender -->
<root level="INFO">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>

View File

@@ -50,8 +50,7 @@
ws.onmessage = function (event) {
if(event.data){
let data = JSON.parse(event.data);
let message = `${data.number} --- [ ${data.threadName} ] <span style="color: #198cff;">${data.name}</span> : ${data.message}`;
logger.log(message, data.level, data.timestamp);
logger.log(data.name + ' : ' + data.message, data.level, data.timestamp);
}
}

View File

@@ -40,10 +40,4 @@
> v2.1.2
```
升级metona-mq-mini-pro到2.0.1
```
> v2.1.3
```
使用ServletContextListener方式获取实时日志
页面日志要素添加进程id和线程名称优化样式
日志打印级别调整为INFO
```