优化文件下载方式.

This commit is contained in:
lijiahang
2024-06-04 18:34:19 +08:00
parent 26a6d08d96
commit 59d9739f36
32 changed files with 197 additions and 56 deletions

View File

@@ -19,6 +19,9 @@ spring:
mvc: mvc:
pathmatch: pathmatch:
matching-strategy: ANT_PATH_MATCHER matching-strategy: ANT_PATH_MATCHER
async:
# 异步请求时间 30min
request-timeout: 1800000
datasource: datasource:
druid: druid:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver

View File

@@ -1,5 +1,5 @@
### 分页查询 SFTP 操作日志 ### 分页查询 SFTP 操作日志
POST {{baseUrl}}/asset/host-sftp-log/query POST {{baseUrl}}/asset/host-sftp/query-log
Content-Type: application/json Content-Type: application/json
Authorization: {{token}} Authorization: {{token}}
@@ -10,8 +10,12 @@ Authorization: {{token}}
### 删除 SFTP 操作日志 ### 删除 SFTP 操作日志
DELETE {{baseUrl}}/asset/host-sftp-log/delete?idList=1,2,3 DELETE {{baseUrl}}/asset/host-sftp/delete-log?idList=1,2,3
Authorization: {{token}} Authorization: {{token}}
### 下载文件
GET {{baseUrl}}/asset/host-sftp/download?channelId=123&transferToken=123
### ###

View File

@@ -5,11 +5,12 @@ import com.orion.visor.framework.biz.operator.log.core.annotation.OperatorLog;
import com.orion.visor.framework.common.validator.group.Page; import com.orion.visor.framework.common.validator.group.Page;
import com.orion.visor.framework.log.core.annotation.IgnoreLog; import com.orion.visor.framework.log.core.annotation.IgnoreLog;
import com.orion.visor.framework.log.core.enums.IgnoreLogMode; import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.IgnoreWrapper;
import com.orion.visor.framework.web.core.annotation.RestWrapper; import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.asset.define.operator.HostTerminalOperatorType; import com.orion.visor.module.asset.define.operator.HostTerminalOperatorType;
import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest; import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest;
import com.orion.visor.module.asset.entity.vo.HostSftpLogVO; import com.orion.visor.module.asset.entity.vo.HostSftpLogVO;
import com.orion.visor.module.asset.service.HostSftpLogService; import com.orion.visor.module.asset.service.HostSftpService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -17,44 +18,59 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
/** /**
* SFTP 操作日志服务 api * SFTP 操作服务 api
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2023-12-26 22:09 * @since 2023-12-26 22:09
*/ */
@Tag(name = "asset - SFTP 操作日志服务") @Tag(name = "asset - SFTP 操作服务")
@Slf4j @Slf4j
@Validated @Validated
@RestWrapper @RestWrapper
@RestController @RestController
@RequestMapping("/asset/host-sftp-log") @RequestMapping("/asset/host-sftp")
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"}) @SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
public class HostSftpLogController { public class HostSftpLogController {
@Resource @Resource
private HostSftpLogService hostSftpLogService; private HostSftpService hostSftpService;
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)
@PostMapping("/query") @PostMapping("/query-log")
@Operation(summary = "分页查询 SFTP 操作日志") @Operation(summary = "分页查询 SFTP 操作日志")
@PreAuthorize("@ss.hasAnyPermission('infra:operator-log:query', 'asset:host-sftp-log:management:query')") @PreAuthorize("@ss.hasAnyPermission('infra:operator-log:query', 'asset:host-sftp-log:management:query')")
public DataGrid<HostSftpLogVO> getHostSftpLogPage(@Validated(Page.class) @RequestBody HostSftpLogQueryRequest request) { public DataGrid<HostSftpLogVO> getHostSftpLogPage(@Validated(Page.class) @RequestBody HostSftpLogQueryRequest request) {
return hostSftpLogService.getHostSftpLogPage(request); return hostSftpService.getHostSftpLogPage(request);
} }
@OperatorLog(HostTerminalOperatorType.DELETE_SFTP_LOG) @OperatorLog(HostTerminalOperatorType.DELETE_SFTP_LOG)
@DeleteMapping("/delete") @DeleteMapping("/delete-log")
@Operation(summary = "删除 SFTP 操作日志") @Operation(summary = "删除 SFTP 操作日志")
@Parameter(name = "idList", description = "idList", required = true) @Parameter(name = "idList", description = "idList", required = true)
@PreAuthorize("@ss.hasAnyPermission('infra:operator-log:delete', 'asset:host-sftp-log:management:delete')") @PreAuthorize("@ss.hasAnyPermission('infra:operator-log:delete', 'asset:host-sftp-log:management:delete')")
public Integer deleteHostSftpLog(@RequestParam("idList") List<Long> idList) { public Integer deleteHostSftpLog(@RequestParam("idList") List<Long> idList) {
return hostSftpLogService.deleteHostSftpLog(idList); return hostSftpService.deleteHostSftpLog(idList);
}
@PermitAll
@IgnoreWrapper
@GetMapping("/download")
@Operation(summary = "下载文件")
@Parameter(name = "channelId", description = "channelId", required = true)
@Parameter(name = "transferToken", description = "transferToken", required = true)
public StreamingResponseBody downloadFile(@RequestParam("channelId") String channelId,
@RequestParam("transferToken") String transferToken,
HttpServletResponse response) {
return hostSftpService.downloadWithTransferToken(channelId, transferToken, response);
} }
} }

View File

@@ -2,7 +2,7 @@ package com.orion.visor.module.asset.handler.host.terminal;
import com.orion.visor.module.asset.define.AssetThreadPools; import com.orion.visor.module.asset.define.AssetThreadPools;
import com.orion.visor.module.asset.handler.host.terminal.enums.InputTypeEnum; import com.orion.visor.module.asset.handler.host.terminal.enums.InputTypeEnum;
import com.orion.visor.module.asset.handler.host.terminal.manager.TerminalManager; import com.orion.visor.module.asset.handler.host.terminal.manager.HostTerminalManager;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
@@ -24,7 +24,7 @@ import javax.annotation.Resource;
public class TerminalMessageDispatcher extends AbstractWebSocketHandler { public class TerminalMessageDispatcher extends AbstractWebSocketHandler {
@Resource @Resource
private TerminalManager terminalManager; private HostTerminalManager hostTerminalManager;
@Override @Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) { protected void handleTextMessage(WebSocketSession session, TextMessage message) {
@@ -65,7 +65,7 @@ public class TerminalMessageDispatcher extends AbstractWebSocketHandler {
String id = session.getId(); String id = session.getId();
log.info("TerminalMessageDispatcher-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason()); log.info("TerminalMessageDispatcher-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
// 关闭会话 // 关闭会话
terminalManager.closeSession(id); hostTerminalManager.closeSession(id);
} }
} }

View File

@@ -7,7 +7,7 @@ import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.constant.ErrorMessage; import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.websocket.core.utils.WebSockets; import com.orion.visor.framework.websocket.core.utils.WebSockets;
import com.orion.visor.module.asset.handler.host.terminal.enums.OutputTypeEnum; import com.orion.visor.module.asset.handler.host.terminal.enums.OutputTypeEnum;
import com.orion.visor.module.asset.handler.host.terminal.manager.TerminalManager; import com.orion.visor.module.asset.handler.host.terminal.manager.HostTerminalManager;
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload; import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig; import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig;
import com.orion.visor.module.asset.handler.host.terminal.session.ITerminalSession; import com.orion.visor.module.asset.handler.host.terminal.session.ITerminalSession;
@@ -27,7 +27,7 @@ import java.util.Map;
public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> implements ITerminalHandler<T> { public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> implements ITerminalHandler<T> {
@Resource @Resource
protected TerminalManager terminalManager; protected HostTerminalManager hostTerminalManager;
@Resource @Resource
private OperatorLogFrameworkService operatorLogFrameworkService; private OperatorLogFrameworkService operatorLogFrameworkService;
@@ -75,7 +75,7 @@ public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> imp
String channelId = channel.getId(); String channelId = channel.getId();
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
// 获取会话并且设置参数 // 获取会话并且设置参数
ITerminalSession session = terminalManager.getSession(channelId, sessionId); ITerminalSession session = hostTerminalManager.getSession(channelId, sessionId);
if (session != null) { if (session != null) {
TerminalConfig config = session.getConfig(); TerminalConfig config = session.getConfig();
extra.put(OperatorLogs.HOST_ID, config.getHostId()); extra.put(OperatorLogs.HOST_ID, config.getHostId());

View File

@@ -30,7 +30,7 @@ public class SftpChangeModHandler extends AbstractTerminalHandler<SftpChangeModR
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
Integer mod = payload.getMod(); Integer mod = payload.getMod();
log.info("SftpChangeModHandler-handle start sessionId: {}, path: {}, mod: {}", sessionId, path, mod); log.info("SftpChangeModHandler-handle start sessionId: {}, path: {}, mod: {}", sessionId, path, mod);

View File

@@ -30,7 +30,7 @@ public class SftpDownloadFlatDirectoryHandler extends AbstractTerminalHandler<Sf
public void handle(WebSocketSession channel, SftpDownloadFlatDirectoryRequest payload) { public void handle(WebSocketSession channel, SftpDownloadFlatDirectoryRequest payload) {
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String[] paths = payload.getPath().split("\\|"); String[] paths = payload.getPath().split("\\|");
log.info("SftpDownloadFlatDirectoryHandler-handle start sessionId: {}, paths: {}", sessionId, Arrays.toString(paths)); log.info("SftpDownloadFlatDirectoryHandler-handle start sessionId: {}, paths: {}", sessionId, Arrays.toString(paths));
Exception ex = null; Exception ex = null;

View File

@@ -25,7 +25,7 @@ public class SftpGetContentHandler extends AbstractTerminalHandler<SftpBaseReque
public void handle(WebSocketSession channel, SftpBaseRequest payload) { public void handle(WebSocketSession channel, SftpBaseRequest payload) {
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpGetContentHandler-handle start sessionId: {}, path: {}", sessionId, path); log.info("SftpGetContentHandler-handle start sessionId: {}, path: {}", sessionId, path);
String content = Const.EMPTY; String content = Const.EMPTY;

View File

@@ -31,7 +31,7 @@ public class SftpListHandler extends AbstractTerminalHandler<SftpListRequest> {
public void handle(WebSocketSession channel, SftpListRequest payload) { public void handle(WebSocketSession channel, SftpListRequest payload) {
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpListHandler-handle start sessionId: {}, path: {}", sessionId, path); log.info("SftpListHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;

View File

@@ -30,7 +30,7 @@ public class SftpMakeDirectoryHandler extends AbstractTerminalHandler<SftpBaseRe
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpMakeDirectoryHandler-handle start sessionId: {}, path: {}", sessionId, path); log.info("SftpMakeDirectoryHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;

View File

@@ -30,7 +30,7 @@ public class SftpMoveHandler extends AbstractTerminalHandler<SftpMoveRequest> {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
String target = payload.getTarget(); String target = payload.getTarget();
log.info("SftpMoveHandler-handle start sessionId: {}, path: {}, target: {}", sessionId, path, target); log.info("SftpMoveHandler-handle start sessionId: {}, path: {}, target: {}", sessionId, path, target);

View File

@@ -31,7 +31,7 @@ public class SftpRemoveHandler extends AbstractTerminalHandler<SftpBaseRequest>
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String[] paths = payload.getPath().split("\\|"); String[] paths = payload.getPath().split("\\|");
log.info("SftpRemoveHandler-handle start sessionId: {}, path: {}", sessionId, Arrays.toString(paths)); log.info("SftpRemoveHandler-handle start sessionId: {}, path: {}", sessionId, Arrays.toString(paths));
Exception ex = null; Exception ex = null;

View File

@@ -30,7 +30,7 @@ public class SftpSetContentHandler extends AbstractTerminalHandler<SftpSetConten
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpSetContentHandler-handle start sessionId: {}, path: {}", sessionId, path); log.info("SftpSetContentHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;

View File

@@ -30,7 +30,7 @@ public class SftpTouchHandler extends AbstractTerminalHandler<SftpBaseRequest> {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpTouchHandler-handle start sessionId: {}, path: {}", sessionId, path); log.info("SftpTouchHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;

View File

@@ -30,7 +30,7 @@ public class SftpTruncateHandler extends AbstractTerminalHandler<SftpBaseRequest
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
// 获取会话 // 获取会话
String sessionId = payload.getSessionId(); String sessionId = payload.getSessionId();
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
String path = payload.getPath(); String path = payload.getPath();
log.info("SftpTruncateHandler-handle start sessionId: {}, path: {}", sessionId, path); log.info("SftpTruncateHandler-handle start sessionId: {}, path: {}", sessionId, path);
Exception ex = null; Exception ex = null;

View File

@@ -20,7 +20,7 @@ public class SshInputHandler extends AbstractTerminalHandler<SshInputRequest> {
@Override @Override
public void handle(WebSocketSession channel, SshInputRequest payload) { public void handle(WebSocketSession channel, SshInputRequest payload) {
// 获取会话 // 获取会话
ISshSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); ISshSession session = hostTerminalManager.getSession(channel.getId(), payload.getSessionId());
// 处理输入 // 处理输入
session.write(payload.getCommand()); session.write(payload.getCommand());
} }

View File

@@ -20,7 +20,7 @@ public class SshResizeHandler extends AbstractTerminalHandler<SshResizeRequest>
@Override @Override
public void handle(WebSocketSession channel, SshResizeRequest payload) { public void handle(WebSocketSession channel, SshResizeRequest payload) {
// 获取会话 // 获取会话
ISshSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); ISshSession session = hostTerminalManager.getSession(channel.getId(), payload.getSessionId());
// 修改大小 // 修改大小
session.resize(payload.getCols(), payload.getRows()); session.resize(payload.getCols(), payload.getRows());
} }

View File

@@ -117,7 +117,7 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
* @return 是否存在 * @return 是否存在
*/ */
private boolean checkSession(WebSocketSession channel, TerminalCheckRequest payload) { private boolean checkSession(WebSocketSession channel, TerminalCheckRequest payload) {
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId()); ITerminalSession session = hostTerminalManager.getSession(channel.getId(), payload.getSessionId());
if (session != null) { if (session != null) {
this.sendCheckFailedMessage(channel, payload, ErrorMessage.SESSION_PRESENT); this.sendCheckFailedMessage(channel, payload, ErrorMessage.SESSION_PRESENT);
return true; return true;

View File

@@ -20,7 +20,7 @@ public class TerminalCloseHandler extends AbstractTerminalHandler<TerminalBasePa
public void handle(WebSocketSession channel, TerminalBasePayload payload) { public void handle(WebSocketSession channel, TerminalBasePayload payload) {
log.info("TerminalCloseHandler-handle start sessionId: {}", payload.getSessionId()); log.info("TerminalCloseHandler-handle start sessionId: {}", payload.getSessionId());
// 关闭会话 // 关闭会话
terminalManager.closeSession(channel.getId(), payload.getSessionId()); hostTerminalManager.closeSession(channel.getId(), payload.getSessionId());
} }
} }

View File

@@ -72,7 +72,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
// 连接主机 // 连接主机
ITerminalSession session = this.connect(sessionId, connect, channel, payload); ITerminalSession session = this.connect(sessionId, connect, channel, payload);
// 添加会话到 manager // 添加会话到 manager
terminalManager.addSession(session); hostTerminalManager.addSession(session);
} catch (Exception e) { } catch (Exception e) {
ex = e; ex = e;
// 修改连接状态为失败 // 修改连接状态为失败

View File

@@ -26,7 +26,7 @@ public class TerminalPingHandler extends AbstractTerminalHandler<TerminalBasePay
// 发送 pong // 发送 pong
this.send(channel, OutputTypeEnum.PONG.getType()); this.send(channel, OutputTypeEnum.PONG.getType());
// 活跃 terminal // 活跃 terminal
Map<String, ITerminalSession> sessions = terminalManager.getSession(channel.getId()); Map<String, ITerminalSession> sessions = hostTerminalManager.getSession(channel.getId());
if (!Maps.isEmpty(sessions)) { if (!Maps.isEmpty(sessions)) {
for (ITerminalSession session : sessions.values()) { for (ITerminalSession session : sessions.values()) {
session.keepAlive(); session.keepAlive();

View File

@@ -10,14 +10,14 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* 终端管理器 * 主机终端管理器
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2024/1/3 11:35 * @since 2024/1/3 11:35
*/ */
@Component @Component
public class TerminalManager { public class HostTerminalManager {
/** /**
* 会话存储器 * 会话存储器

View File

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.orion.lang.utils.io.Streams; import com.orion.lang.utils.io.Streams;
import com.orion.visor.module.asset.handler.host.transfer.handler.ITransferHandler; import com.orion.visor.module.asset.handler.host.transfer.handler.ITransferHandler;
import com.orion.visor.module.asset.handler.host.transfer.handler.TransferHandler; import com.orion.visor.module.asset.handler.host.transfer.handler.TransferHandler;
import com.orion.visor.module.asset.handler.host.transfer.manager.HostTransferManager;
import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorRequest; import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -13,7 +14,7 @@ import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler; import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Resource;
/** /**
* sftp 传输消息处理器 * sftp 传输消息处理器
@@ -26,24 +27,30 @@ import java.util.concurrent.ConcurrentHashMap;
@Component @Component
public class TransferMessageDispatcher extends AbstractWebSocketHandler { public class TransferMessageDispatcher extends AbstractWebSocketHandler {
private final ConcurrentHashMap<String, ITransferHandler> handlers = new ConcurrentHashMap<>(); @Resource
private HostTransferManager hostTransferManager;
@Override
public void afterConnectionEstablished(WebSocketSession session) {
log.info("TransferMessageHandler-afterConnectionEstablished id: {}", session.getId());
// 添加处理器
hostTransferManager.putHandler(session.getId(), new TransferHandler(session));
}
@Override @Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) { protected void handleTextMessage(WebSocketSession session, TextMessage message) {
// 获取处理器 // 获取处理器
ITransferHandler handler = handlers.computeIfAbsent(session.getId(), s -> new TransferHandler(session)); ITransferHandler handler = hostTransferManager.getHandler(session.getId());
// 处理消息 // 处理消息
handler.handleMessage(JSON.parseObject(message.getPayload(), TransferOperatorRequest.class)); handler.handleMessage(JSON.parseObject(message.getPayload(), TransferOperatorRequest.class));
} }
@Override @Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) { protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
handlers.get(session.getId()).putContent(message.getPayload().array()); // 获取处理器
} ITransferHandler handler = hostTransferManager.getHandler(session.getId());
// 添加数据
@Override handler.putContent(message.getPayload().array());
public void afterConnectionEstablished(WebSocketSession session) {
log.info("TransferMessageHandler-afterConnectionEstablished id: {}", session.getId());
} }
@Override @Override
@@ -56,7 +63,7 @@ public class TransferMessageDispatcher extends AbstractWebSocketHandler {
String id = session.getId(); String id = session.getId();
log.info("TransferMessageHandler-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason()); log.info("TransferMessageHandler-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
// 关闭会话 // 关闭会话
Streams.close(handlers.remove(id)); Streams.close(hostTransferManager.removeHandler(id));
} }
} }

View File

@@ -45,7 +45,7 @@ public enum TransferOperatorType {
public static final String DOWNLOAD = "DOWNLOAD"; public static final String DOWNLOAD = "DOWNLOAD";
private final String operator; private final String kind;
private final String type; private final String type;

View File

@@ -39,6 +39,16 @@ public enum TransferReceiverType {
*/ */
DOWNLOAD_FINISH("downloadFinish"), DOWNLOAD_FINISH("downloadFinish"),
/**
* 开始下载
*/
DOWNLOAD_START("downloadStart"),
/**
* 下载进度
*/
DOWNLOAD_PROGRESS("downloadProgress"),
/** /**
* 下载失败 * 下载失败
*/ */

View File

@@ -2,6 +2,9 @@ package com.orion.visor.module.asset.handler.host.transfer.handler;
import com.orion.lang.able.SafeCloseable; import com.orion.lang.able.SafeCloseable;
import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorRequest; import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorRequest;
import com.orion.visor.module.asset.handler.host.transfer.session.IDownloadSession;
import java.util.Map;
/** /**
* 传输处理器定义 * 传输处理器定义
@@ -26,4 +29,11 @@ public interface ITransferHandler extends SafeCloseable {
*/ */
void putContent(byte[] content); void putContent(byte[] content);
/**
* 获取 token sessions
*
* @return token sessions
*/
Map<String, IDownloadSession> getTokenSessions();
} }

View File

@@ -0,0 +1,50 @@
package com.orion.visor.module.asset.handler.host.transfer.manager;
import com.orion.visor.module.asset.handler.host.transfer.handler.ITransferHandler;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
/**
* 主机传输管理器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/6/4 17:58
*/
@Component
public class HostTransferManager {
private final ConcurrentHashMap<String, ITransferHandler> handlers = new ConcurrentHashMap<>();
/**
* 添加处理器
*
* @param id id
* @param handler handler
*/
public void putHandler(String id, ITransferHandler handler) {
handlers.put(id, handler);
}
/**
* 获取处理器
*
* @param id id
* @return handler
*/
public ITransferHandler getHandler(String id) {
return handlers.get(id);
}
/**
* 删除处理器
*
* @param id id
* @return handler
*/
public ITransferHandler removeHandler(String id) {
return handlers.remove(id);
}
}

View File

@@ -20,7 +20,7 @@ import lombok.NoArgsConstructor;
@Schema(name = "FileOperatorRequest", description = "文件操作请求 实体对象") @Schema(name = "FileOperatorRequest", description = "文件操作请求 实体对象")
public class TransferOperatorRequest { public class TransferOperatorRequest {
@Schema(description = "上传路径") @Schema(description = "文件路径")
private String path; private String path;
@Schema(description = "type") @Schema(description = "type")

View File

@@ -1,5 +1,7 @@
package com.orion.visor.module.asset.handler.host.transfer.session; package com.orion.visor.module.asset.handler.host.transfer.session;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
/** /**
* 下载会话定义 * 下载会话定义
* *
@@ -7,18 +9,26 @@ package com.orion.visor.module.asset.handler.host.transfer.session;
* @version 1.0.0 * @version 1.0.0
* @since 2024/2/22 22:25 * @since 2024/2/22 22:25
*/ */
public interface IDownloadSession { public interface IDownloadSession extends StreamingResponseBody {
/** /**
* 开始下载 * 开始下载
* *
* @param path path * @param path path
* @param token token
*/ */
void startDownload(String path); void startDownload(String path, String token);
/** /**
* 停止下载 * 停止下载
*/ */
void abortDownload(); void abortDownload();
/**
* 获取下载文件路径
*
* @return path
*/
String getPath();
} }

View File

@@ -8,6 +8,8 @@ import com.orion.visor.module.asset.handler.host.transfer.enums.TransferReceiver
import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorResponse; import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorResponse;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.util.function.Consumer;
/** /**
* 传输工具类 * 传输工具类
* *
@@ -28,11 +30,26 @@ public class TransferUtils {
* @param ex ex * @param ex ex
*/ */
public static void sendMessage(WebSocketSession channel, TransferReceiverType type, Exception ex) { public static void sendMessage(WebSocketSession channel, TransferReceiverType type, Exception ex) {
sendMessage(channel, type, ex, null);
}
/**
* 发送消息
*
* @param channel channel
* @param type type
* @param ex ex
* @param filler filler
*/
public static void sendMessage(WebSocketSession channel, TransferReceiverType type, Exception ex, Consumer<TransferOperatorResponse> filler) {
TransferOperatorResponse resp = TransferOperatorResponse.builder() TransferOperatorResponse resp = TransferOperatorResponse.builder()
.type(type.getType()) .type(type.getType())
.success(ex == null) .success(ex == null)
.msg(TransferUtils.getErrorMessage(ex)) .msg(TransferUtils.getErrorMessage(ex))
.build(); .build();
if (filler != null) {
filler.accept(resp);
}
WebSockets.sendText(channel, JSON.toJSONString(resp)); WebSockets.sendText(channel, JSON.toJSONString(resp));
} }

View File

@@ -3,17 +3,19 @@ package com.orion.visor.module.asset.service;
import com.orion.lang.define.wrapper.DataGrid; import com.orion.lang.define.wrapper.DataGrid;
import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest; import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest;
import com.orion.visor.module.asset.entity.vo.HostSftpLogVO; import com.orion.visor.module.asset.entity.vo.HostSftpLogVO;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
/** /**
* SFTP 操作日志 服务类 * SFTP 操作 服务类
* *
* @author Jiahang Li * @author Jiahang Li
* @version 1.0.0 * @version 1.0.0
* @since 2023-12-26 22:09 * @since 2023-12-26 22:09
*/ */
public interface HostSftpLogService { public interface HostSftpService {
/** /**
* 分页查询 SFTP 操作日志 * 分页查询 SFTP 操作日志
@@ -31,4 +33,16 @@ public interface HostSftpLogService {
*/ */
Integer deleteHostSftpLog(List<Long> idList); Integer deleteHostSftpLog(List<Long> idList);
/**
* 通过 transferToken 下载
*
* @param channelId channelId
* @param transferToken transferToken
* @param response response
* @return body
*/
StreamingResponseBody downloadWithTransferToken(String channelId,
String transferToken,
HttpServletResponse response);
} }

View File

@@ -19,7 +19,7 @@ import com.orion.visor.module.asset.entity.request.host.HostConnectLogQueryReque
import com.orion.visor.module.asset.entity.vo.HostConnectLogVO; import com.orion.visor.module.asset.entity.vo.HostConnectLogVO;
import com.orion.visor.module.asset.enums.HostConnectStatusEnum; import com.orion.visor.module.asset.enums.HostConnectStatusEnum;
import com.orion.visor.module.asset.enums.HostConnectTypeEnum; import com.orion.visor.module.asset.enums.HostConnectTypeEnum;
import com.orion.visor.module.asset.handler.host.terminal.manager.TerminalManager; import com.orion.visor.module.asset.handler.host.terminal.manager.HostTerminalManager;
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig; import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig;
import com.orion.visor.module.asset.handler.host.terminal.session.ITerminalSession; import com.orion.visor.module.asset.handler.host.terminal.session.ITerminalSession;
import com.orion.visor.module.asset.service.HostConnectLogService; import com.orion.visor.module.asset.service.HostConnectLogService;
@@ -49,7 +49,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
private HostConnectLogDAO hostConnectLogDAO; private HostConnectLogDAO hostConnectLogDAO;
@Resource @Resource
private TerminalManager terminalManager; private HostTerminalManager hostTerminalManager;
@Override @Override
public Long create(HostConnectTypeEnum type, HostConnectLogCreateRequest request) { public Long create(HostConnectTypeEnum type, HostConnectLogCreateRequest request) {
@@ -84,7 +84,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
@Override @Override
public List<HostConnectLogVO> getHostConnectSessions(HostConnectLogQueryRequest request) { public List<HostConnectLogVO> getHostConnectSessions(HostConnectLogQueryRequest request) {
// 查询全部 // 查询全部
List<Long> idList = terminalManager.getChannelSessions() List<Long> idList = hostTerminalManager.getChannelSessions()
.values() .values()
.stream() .stream()
.map(ConcurrentHashMap::values) .map(ConcurrentHashMap::values)
@@ -204,7 +204,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
OperatorLogs.add(OperatorLogs.HOST_NAME, record.getHostName()); OperatorLogs.add(OperatorLogs.HOST_NAME, record.getHostName());
// 获取会话 // 获取会话
HostConnectLogExtraDTO extra = JSON.parseObject(record.getExtraInfo(), HostConnectLogExtraDTO.class); HostConnectLogExtraDTO extra = JSON.parseObject(record.getExtraInfo(), HostConnectLogExtraDTO.class);
ITerminalSession session = terminalManager.getSession(extra.getChannelId(), extra.getSessionId()); ITerminalSession session = hostTerminalManager.getSession(extra.getChannelId(), extra.getSessionId());
if (session != null) { if (session != null) {
// 关闭会话 // 关闭会话
session.forceOffline(); session.forceOffline();