⚡ 优化文件下载逻辑.
This commit is contained in:
@@ -18,6 +18,7 @@ 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.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -60,6 +61,24 @@ public class HostSftpLogController {
|
|||||||
return hostSftpService.deleteHostSftpLog(idList);
|
return hostSftpService.deleteHostSftpLog(idList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
|
@GetMapping("/get-content")
|
||||||
|
@Operation(summary = "获取文件内容")
|
||||||
|
@Parameter(name = "token", description = "token", required = true)
|
||||||
|
public void getFileContentByToken(@RequestParam("token") String token, HttpServletResponse response) throws Exception {
|
||||||
|
hostSftpService.getFileContentByToken(token, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/set-content")
|
||||||
|
@Operation(summary = "设置文件内容")
|
||||||
|
@Parameter(name = "token", description = "token", required = true)
|
||||||
|
@Parameter(name = "file", description = "file", required = true)
|
||||||
|
public Boolean setFileContentByToken(@RequestParam("token") String token,
|
||||||
|
@RequestParam("file") MultipartFile file) throws Exception {
|
||||||
|
hostSftpService.setFileContentByToken(token, file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@IgnoreWrapper
|
@IgnoreWrapper
|
||||||
@IgnoreLog(IgnoreLogMode.RET)
|
@IgnoreLog(IgnoreLogMode.RET)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import com.orion.lang.define.cache.key.CacheKeyDefine;
|
|||||||
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
|
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
|
||||||
import com.orion.visor.module.asset.entity.dto.HostTerminalAccessDTO;
|
import com.orion.visor.module.asset.entity.dto.HostTerminalAccessDTO;
|
||||||
import com.orion.visor.module.asset.entity.dto.HostTerminalTransferDTO;
|
import com.orion.visor.module.asset.entity.dto.HostTerminalTransferDTO;
|
||||||
|
import com.orion.visor.module.asset.entity.dto.SftpGetContentCacheDTO;
|
||||||
|
import com.orion.visor.module.asset.entity.dto.SftpSetContentCacheDTO;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -33,4 +35,20 @@ public interface HostTerminalCacheKeyDefine {
|
|||||||
.timeout(3, TimeUnit.MINUTES)
|
.timeout(3, TimeUnit.MINUTES)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
CacheKeyDefine SFTP_GET_CONTENT = new CacheKeyBuilder()
|
||||||
|
.key("sftp:get:content:{}")
|
||||||
|
.desc("sftp 获取文件内容 ${token}")
|
||||||
|
.type(SftpGetContentCacheDTO.class)
|
||||||
|
.struct(RedisCacheStruct.STRING)
|
||||||
|
.timeout(5, TimeUnit.MINUTES)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CacheKeyDefine SFTP_SET_CONTENT = new CacheKeyBuilder()
|
||||||
|
.key("sftp:set:content:{}")
|
||||||
|
.desc("sftp 设置文件内容 ${token}")
|
||||||
|
.type(SftpSetContentCacheDTO.class)
|
||||||
|
.struct(RedisCacheStruct.STRING)
|
||||||
|
.timeout(5, TimeUnit.MINUTES)
|
||||||
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.orion.visor.module.asset.entity.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 获取文件内容缓存对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/10/10 20:49
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "SftpGetContentCacheDTO", description = "sftp 获取文件内容缓存对象")
|
||||||
|
public class SftpGetContentCacheDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主机id")
|
||||||
|
private Long hostId;
|
||||||
|
|
||||||
|
@Schema(description = "文件路径")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.orion.visor.module.asset.entity.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 获取文件内容缓存对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/10/10 20:49
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "SftpSetContentCacheDTO", description = "sftp 设置文件内容缓存对象")
|
||||||
|
public class SftpSetContentCacheDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主机id")
|
||||||
|
private Long hostId;
|
||||||
|
|
||||||
|
@Schema(description = "文件路径")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -159,8 +159,8 @@ public enum InputTypeEnum {
|
|||||||
*/
|
*/
|
||||||
SFTP_SET_CONTENT("sc",
|
SFTP_SET_CONTENT("sc",
|
||||||
SftpSetContentHandler.class,
|
SftpSetContentHandler.class,
|
||||||
new String[]{"type", "sessionId", "path", "content"},
|
new String[]{"type", "sessionId", "path"},
|
||||||
SftpSetContentRequest.class,
|
SftpBaseRequest.class,
|
||||||
true),
|
true),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ public enum OutputTypeEnum {
|
|||||||
/**
|
/**
|
||||||
* SFTP 获取文件内容
|
* SFTP 获取文件内容
|
||||||
*/
|
*/
|
||||||
SFTP_GET_CONTENT("gc", "${type}|${sessionId}|${path}|${result}|${msg}|${content}"),
|
SFTP_GET_CONTENT("gc", "${type}|${sessionId}|${result}|${msg}|${token}"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SFTP 修改文件内容
|
* SFTP 修改文件内容
|
||||||
*/
|
*/
|
||||||
SFTP_SET_CONTENT("sc", "${type}|${sessionId}|${result}|${msg}"),
|
SFTP_SET_CONTENT("sc", "${type}|${sessionId}|${result}|${msg}|${token}"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.orion.visor.module.asset.handler.host.terminal.handler;
|
package com.orion.visor.module.asset.handler.host.terminal.handler;
|
||||||
|
|
||||||
import com.orion.visor.framework.common.constant.Const;
|
import com.orion.lang.id.UUIds;
|
||||||
import com.orion.visor.framework.common.enums.BooleanBit;
|
import com.orion.visor.framework.common.enums.BooleanBit;
|
||||||
|
import com.orion.visor.framework.redis.core.utils.RedisStrings;
|
||||||
|
import com.orion.visor.module.asset.define.cache.HostTerminalCacheKeyDefine;
|
||||||
|
import com.orion.visor.module.asset.entity.dto.SftpGetContentCacheDTO;
|
||||||
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.model.request.SftpBaseRequest;
|
import com.orion.visor.module.asset.handler.host.terminal.model.request.SftpBaseRequest;
|
||||||
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpGetContentResponse;
|
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpGetContentResponse;
|
||||||
@@ -28,11 +31,18 @@ public class SftpGetContentHandler extends AbstractTerminalHandler<SftpBaseReque
|
|||||||
ISftpSession session = hostTerminalManager.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 token = UUIds.random32();
|
||||||
Exception ex = null;
|
Exception ex = null;
|
||||||
// 获取内容
|
|
||||||
try {
|
try {
|
||||||
content = session.getContent(path);
|
// 检查文件是否可编辑
|
||||||
|
session.checkCanEdit(path);
|
||||||
|
// 设置缓存
|
||||||
|
String key = HostTerminalCacheKeyDefine.SFTP_GET_CONTENT.format(token);
|
||||||
|
SftpGetContentCacheDTO cache = SftpGetContentCacheDTO.builder()
|
||||||
|
.hostId(session.getConfig().getHostId())
|
||||||
|
.path(path)
|
||||||
|
.build();
|
||||||
|
RedisStrings.setJson(key, HostTerminalCacheKeyDefine.SFTP_GET_CONTENT, cache);
|
||||||
log.info("SftpGetContentHandler-handle success sessionId: {}, path: {}", sessionId, path);
|
log.info("SftpGetContentHandler-handle success sessionId: {}, path: {}", sessionId, path);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("SftpGetContentHandler-handle error sessionId: {}", sessionId, e);
|
log.error("SftpGetContentHandler-handle error sessionId: {}", sessionId, e);
|
||||||
@@ -44,7 +54,7 @@ public class SftpGetContentHandler extends AbstractTerminalHandler<SftpBaseReque
|
|||||||
SftpGetContentResponse.builder()
|
SftpGetContentResponse.builder()
|
||||||
.sessionId(sessionId)
|
.sessionId(sessionId)
|
||||||
.result(BooleanBit.of(ex == null).getValue())
|
.result(BooleanBit.of(ex == null).getValue())
|
||||||
.content(content)
|
.token(token)
|
||||||
.msg(this.getErrorMessage(ex))
|
.msg(this.getErrorMessage(ex))
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package com.orion.visor.module.asset.handler.host.terminal.handler;
|
package com.orion.visor.module.asset.handler.host.terminal.handler;
|
||||||
|
|
||||||
|
import com.orion.lang.id.UUIds;
|
||||||
import com.orion.lang.utils.collect.Maps;
|
import com.orion.lang.utils.collect.Maps;
|
||||||
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||||
import com.orion.visor.framework.common.enums.BooleanBit;
|
import com.orion.visor.framework.common.enums.BooleanBit;
|
||||||
|
import com.orion.visor.framework.redis.core.utils.RedisStrings;
|
||||||
|
import com.orion.visor.module.asset.define.cache.HostTerminalCacheKeyDefine;
|
||||||
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.dto.SftpSetContentCacheDTO;
|
||||||
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.model.request.SftpSetContentRequest;
|
import com.orion.visor.module.asset.handler.host.terminal.model.request.SftpBaseRequest;
|
||||||
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpBaseResponse;
|
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpSetContentResponse;
|
||||||
import com.orion.visor.module.asset.handler.host.terminal.session.ISftpSession;
|
import com.orion.visor.module.asset.handler.host.terminal.session.ISftpSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -23,20 +27,28 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class SftpSetContentHandler extends AbstractTerminalHandler<SftpSetContentRequest> {
|
public class SftpSetContentHandler extends AbstractTerminalHandler<SftpBaseRequest> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, SftpSetContentRequest payload) {
|
public void handle(WebSocketSession channel, SftpBaseRequest payload) {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
// 获取会话
|
// 获取会话
|
||||||
String sessionId = payload.getSessionId();
|
String sessionId = payload.getSessionId();
|
||||||
ISftpSession session = hostTerminalManager.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);
|
||||||
|
String token = UUIds.random32();
|
||||||
Exception ex = null;
|
Exception ex = null;
|
||||||
// 修改内容
|
|
||||||
try {
|
try {
|
||||||
session.setContent(path, payload.getContent());
|
// 检查文件是否可编辑
|
||||||
|
session.checkCanEdit(path);
|
||||||
|
// 设置缓存
|
||||||
|
String key = HostTerminalCacheKeyDefine.SFTP_SET_CONTENT.format(token);
|
||||||
|
SftpSetContentCacheDTO cache = SftpSetContentCacheDTO.builder()
|
||||||
|
.hostId(session.getConfig().getHostId())
|
||||||
|
.path(path)
|
||||||
|
.build();
|
||||||
|
RedisStrings.setJson(key, HostTerminalCacheKeyDefine.SFTP_SET_CONTENT, cache);
|
||||||
log.info("SftpSetContentHandler-handle success sessionId: {}, path: {}", sessionId, path);
|
log.info("SftpSetContentHandler-handle success sessionId: {}, path: {}", sessionId, path);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("SftpSetContentHandler-handle error sessionId: {}", sessionId, e);
|
log.error("SftpSetContentHandler-handle error sessionId: {}", sessionId, e);
|
||||||
@@ -45,9 +57,10 @@ public class SftpSetContentHandler extends AbstractTerminalHandler<SftpSetConten
|
|||||||
// 返回
|
// 返回
|
||||||
this.send(channel,
|
this.send(channel,
|
||||||
OutputTypeEnum.SFTP_SET_CONTENT,
|
OutputTypeEnum.SFTP_SET_CONTENT,
|
||||||
SftpBaseResponse.builder()
|
SftpSetContentResponse.builder()
|
||||||
.sessionId(sessionId)
|
.sessionId(sessionId)
|
||||||
.result(BooleanBit.of(ex == null).getValue())
|
.result(BooleanBit.of(ex == null).getValue())
|
||||||
|
.token(token)
|
||||||
.msg(this.getErrorMessage(ex))
|
.msg(this.getErrorMessage(ex))
|
||||||
.build());
|
.build());
|
||||||
// 保存操作日志
|
// 保存操作日志
|
||||||
|
|||||||
@@ -20,14 +20,9 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class SftpGetContentResponse extends SftpBaseResponse {
|
public class SftpGetContentResponse extends SftpBaseResponse {
|
||||||
|
|
||||||
/**
|
|
||||||
* path
|
|
||||||
*/
|
|
||||||
private String path;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* content
|
* content
|
||||||
*/
|
*/
|
||||||
private String content;
|
private String token;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -7,24 +7,22 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sftp 设置文件内容 实体对象
|
* sftp 设置内容响应
|
||||||
* <p>
|
|
||||||
* i|eff00a1|path|content
|
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
* @since 2024/2/6 13:31
|
* @since 2024/2/6 16:20
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@SuperBuilder
|
@SuperBuilder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class SftpSetContentRequest extends SftpBaseRequest {
|
public class SftpSetContentResponse extends SftpBaseResponse {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* content
|
* content
|
||||||
*/
|
*/
|
||||||
private String content;
|
private String token;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -102,4 +102,11 @@ public interface ISftpSession extends ITerminalSession {
|
|||||||
*/
|
*/
|
||||||
void setContent(String path, String content);
|
void setContent(String path, String content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测文件是否可编辑
|
||||||
|
*
|
||||||
|
* @param path path
|
||||||
|
*/
|
||||||
|
void checkCanEdit(String path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.orion.net.host.SessionStore;
|
|||||||
import com.orion.net.host.sftp.SftpExecutor;
|
import com.orion.net.host.sftp.SftpExecutor;
|
||||||
import com.orion.net.host.sftp.SftpFile;
|
import com.orion.net.host.sftp.SftpFile;
|
||||||
import com.orion.visor.framework.common.constant.Const;
|
import com.orion.visor.framework.common.constant.Const;
|
||||||
|
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||||
import com.orion.visor.framework.common.utils.Valid;
|
import com.orion.visor.framework.common.utils.Valid;
|
||||||
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.model.response.SftpFileVO;
|
import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpFileVO;
|
||||||
@@ -145,6 +146,13 @@ public class SftpSession extends TerminalSession implements ISftpSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkCanEdit(String path) {
|
||||||
|
path = Valid.checkNormalize(path);
|
||||||
|
// 检查文件是否存在
|
||||||
|
Valid.isTrue(executor.isExist(path), ErrorMessage.FILE_ABSENT);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keepAlive() {
|
public void keepAlive() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ 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.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,6 +35,24 @@ public interface HostSftpService {
|
|||||||
*/
|
*/
|
||||||
Integer deleteHostSftpLog(List<Long> idList);
|
Integer deleteHostSftpLog(List<Long> idList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置文件内容
|
||||||
|
*
|
||||||
|
* @param token token
|
||||||
|
* @param response response
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
void getFileContentByToken(String token, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件内容
|
||||||
|
*
|
||||||
|
* @param token token
|
||||||
|
* @param file file
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
void setFileContentByToken(String token, MultipartFile file) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 transferToken 下载
|
* 通过 transferToken 下载
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,29 +4,47 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.orion.lang.constant.StandardContentType;
|
import com.orion.lang.constant.StandardContentType;
|
||||||
import com.orion.lang.define.wrapper.DataGrid;
|
import com.orion.lang.define.wrapper.DataGrid;
|
||||||
|
import com.orion.lang.define.wrapper.HttpWrapper;
|
||||||
import com.orion.lang.utils.Arrays1;
|
import com.orion.lang.utils.Arrays1;
|
||||||
|
import com.orion.lang.utils.Exceptions;
|
||||||
import com.orion.lang.utils.Strings;
|
import com.orion.lang.utils.Strings;
|
||||||
|
import com.orion.lang.utils.Valid;
|
||||||
import com.orion.lang.utils.io.Files1;
|
import com.orion.lang.utils.io.Files1;
|
||||||
|
import com.orion.lang.utils.io.Streams;
|
||||||
|
import com.orion.net.host.SessionStore;
|
||||||
|
import com.orion.net.host.sftp.SftpExecutor;
|
||||||
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||||
import com.orion.visor.framework.common.constant.Const;
|
import com.orion.visor.framework.common.constant.Const;
|
||||||
import com.orion.visor.framework.common.constant.ErrorMessage;
|
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||||
import com.orion.visor.framework.common.constant.ExtraFieldConst;
|
import com.orion.visor.framework.common.constant.ExtraFieldConst;
|
||||||
|
import com.orion.visor.framework.redis.core.utils.RedisStrings;
|
||||||
|
import com.orion.visor.framework.security.core.utils.SecurityUtils;
|
||||||
import com.orion.visor.module.asset.convert.HostSftpLogConvert;
|
import com.orion.visor.module.asset.convert.HostSftpLogConvert;
|
||||||
|
import com.orion.visor.module.asset.define.cache.HostTerminalCacheKeyDefine;
|
||||||
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.dto.HostTerminalConnectDTO;
|
||||||
|
import com.orion.visor.module.asset.entity.dto.SftpGetContentCacheDTO;
|
||||||
|
import com.orion.visor.module.asset.entity.dto.SftpSetContentCacheDTO;
|
||||||
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.handler.host.jsch.SessionStores;
|
||||||
import com.orion.visor.module.asset.handler.host.transfer.manager.HostTransferManager;
|
import com.orion.visor.module.asset.handler.host.transfer.manager.HostTransferManager;
|
||||||
import com.orion.visor.module.asset.handler.host.transfer.session.DownloadSession;
|
import com.orion.visor.module.asset.handler.host.transfer.session.DownloadSession;
|
||||||
import com.orion.visor.module.asset.service.HostSftpService;
|
import com.orion.visor.module.asset.service.HostSftpService;
|
||||||
|
import com.orion.visor.module.asset.service.HostTerminalService;
|
||||||
import com.orion.visor.module.infra.api.OperatorLogApi;
|
import com.orion.visor.module.infra.api.OperatorLogApi;
|
||||||
import com.orion.visor.module.infra.entity.dto.operator.OperatorLogQueryDTO;
|
import com.orion.visor.module.infra.entity.dto.operator.OperatorLogQueryDTO;
|
||||||
import com.orion.web.servlet.web.Servlets;
|
import com.orion.web.servlet.web.Servlets;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -47,6 +65,9 @@ public class HostSftpServiceImpl implements HostSftpService {
|
|||||||
@Resource
|
@Resource
|
||||||
private HostTransferManager hostTransferManager;
|
private HostTransferManager hostTransferManager;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HostTerminalService hostTerminalService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataGrid<HostSftpLogVO> getHostSftpLogPage(HostSftpLogQueryRequest request) {
|
public DataGrid<HostSftpLogVO> getHostSftpLogPage(HostSftpLogQueryRequest request) {
|
||||||
// 查询
|
// 查询
|
||||||
@@ -78,6 +99,73 @@ public class HostSftpServiceImpl implements HostSftpService {
|
|||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getFileContentByToken(String token, HttpServletResponse response) throws IOException {
|
||||||
|
// 解析 token
|
||||||
|
String key = HostTerminalCacheKeyDefine.SFTP_GET_CONTENT.format(token);
|
||||||
|
SftpGetContentCacheDTO cache = RedisStrings.getJson(key, HostTerminalCacheKeyDefine.SFTP_GET_CONTENT);
|
||||||
|
if (cache == null) {
|
||||||
|
Servlets.writeHttpWrapper(response, HttpWrapper.error(ErrorMessage.FILE_ABSENT));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 删除缓存
|
||||||
|
RedisStrings.delete(key);
|
||||||
|
// 获取文件内容
|
||||||
|
SessionStore sessionStore = null;
|
||||||
|
SftpExecutor executor = null;
|
||||||
|
InputStream in = null;
|
||||||
|
try {
|
||||||
|
// 获取终端连接信息
|
||||||
|
HostTerminalConnectDTO connectInfo = hostTerminalService.getTerminalConnectInfo(SecurityUtils.getLoginUserId(), cache.getHostId());
|
||||||
|
sessionStore = SessionStores.openSessionStore(connectInfo);
|
||||||
|
executor = sessionStore.getSftpExecutor(connectInfo.getFileNameCharset());
|
||||||
|
executor.connect();
|
||||||
|
// 读取文件
|
||||||
|
in = executor.openInputStream(cache.getPath());
|
||||||
|
// 设置返回
|
||||||
|
Servlets.setContentType(response, StandardContentType.TEXT_PLAIN);
|
||||||
|
Servlets.transfer(response, in);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Servlets.writeHttpWrapper(response, HttpWrapper.error(ErrorMessage.FILE_READ_ERROR));
|
||||||
|
} finally {
|
||||||
|
Streams.close(executor);
|
||||||
|
Streams.close(sessionStore);
|
||||||
|
Streams.close(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFileContentByToken(String token, MultipartFile file) {
|
||||||
|
// 解析 token
|
||||||
|
String key = HostTerminalCacheKeyDefine.SFTP_SET_CONTENT.format(token);
|
||||||
|
SftpSetContentCacheDTO cache = RedisStrings.getJson(key, HostTerminalCacheKeyDefine.SFTP_SET_CONTENT);
|
||||||
|
Valid.notNull(cache, ErrorMessage.FILE_ABSENT);
|
||||||
|
// 删除缓存
|
||||||
|
RedisStrings.delete(key);
|
||||||
|
// 写入文件内容
|
||||||
|
SessionStore sessionStore = null;
|
||||||
|
SftpExecutor executor = null;
|
||||||
|
OutputStream out = null;
|
||||||
|
InputStream in = null;
|
||||||
|
try {
|
||||||
|
// 获取终端连接信息
|
||||||
|
HostTerminalConnectDTO connectInfo = hostTerminalService.getTerminalConnectInfo(SecurityUtils.getLoginUserId(), cache.getHostId());
|
||||||
|
sessionStore = SessionStores.openSessionStore(connectInfo);
|
||||||
|
executor = sessionStore.getSftpExecutor(connectInfo.getFileNameCharset());
|
||||||
|
executor.connect();
|
||||||
|
// 写入文件
|
||||||
|
out = executor.openOutputStream(cache.getPath());
|
||||||
|
Streams.transfer(in = file.getInputStream(), out);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw Exceptions.app(ErrorMessage.OPERATE_ERROR);
|
||||||
|
} finally {
|
||||||
|
Streams.close(executor);
|
||||||
|
Streams.close(sessionStore);
|
||||||
|
Streams.close(out);
|
||||||
|
Streams.close(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamingResponseBody downloadWithTransferToken(String channelId, String transferToken, HttpServletResponse response) {
|
public StreamingResponseBody downloadWithTransferToken(String channelId, String transferToken, HttpServletResponse response) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
|
|||||||
@@ -63,10 +63,35 @@ export function deleteHostSftpLog(idList: Array<number>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 SFTP 文件内容
|
||||||
|
*/
|
||||||
|
export function getSftpFileContent(token: string) {
|
||||||
|
return axios.get<string>('/asset/host-sftp/get-content', {
|
||||||
|
unwrap: true,
|
||||||
|
params: { token },
|
||||||
|
timeout: 60000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 SFTP 文件内容
|
||||||
|
*/
|
||||||
|
export function setSftpFileContent(token: string, content: string) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('token', token);
|
||||||
|
formData.append('file', new File([content], Date.now() + '', { type: 'text/plain' }));
|
||||||
|
return axios.post<boolean>('/asset/host-sftp/set-content', formData, {
|
||||||
|
timeout: 60000,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载文件
|
* 下载文件
|
||||||
*/
|
*/
|
||||||
export function getDownloadTransferUrl(channelId: string, transferToken: string) {
|
export function getDownloadTransferUrl(channelId: string, transferToken: string) {
|
||||||
return `${httpBaseUrl}/asset/host-sftp/download?channelId=${channelId}&transferToken=${transferToken}`;
|
return `${httpBaseUrl}/asset/host-sftp/download?channelId=${channelId}&transferToken=${transferToken}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ export const InputProtocol = {
|
|||||||
// SFTP 修改内容
|
// SFTP 修改内容
|
||||||
SFTP_SET_CONTENT: {
|
SFTP_SET_CONTENT: {
|
||||||
type: 'sc',
|
type: 'sc',
|
||||||
template: ['type', 'sessionId', 'path', 'content']
|
template: ['type', 'sessionId', 'path']
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,13 +181,13 @@ export const OutputProtocol = {
|
|||||||
// SFTP 获取文件内容
|
// SFTP 获取文件内容
|
||||||
SFTP_GET_CONTENT: {
|
SFTP_GET_CONTENT: {
|
||||||
type: 'gc',
|
type: 'gc',
|
||||||
template: ['type', 'sessionId', 'path', 'result', 'msg', 'content'],
|
template: ['type', 'sessionId', 'result', 'msg', 'token'],
|
||||||
processMethod: 'processSftpGetContent'
|
processMethod: 'processSftpGetContent'
|
||||||
},
|
},
|
||||||
// SFTP 修改文件内容
|
// SFTP 修改文件内容
|
||||||
SFTP_SET_CONTENT: {
|
SFTP_SET_CONTENT: {
|
||||||
type: 'sc',
|
type: 'sc',
|
||||||
template: ['type', 'sessionId', 'result', 'msg'],
|
template: ['type', 'sessionId', 'result', 'msg', 'token'],
|
||||||
processMethod: 'processSftpSetContent'
|
processMethod: 'processSftpSetContent'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,22 @@ export function getBase64Data(e: string) {
|
|||||||
return e.substring(e.indexOf(',') + 1);
|
return e.substring(e.indexOf(',') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取 blob 内容 返回 promise
|
||||||
|
*/
|
||||||
|
export function readBlobText(blob: Blob) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = event => {
|
||||||
|
resolve(event.target?.result as string);
|
||||||
|
};
|
||||||
|
reader.onerror = err => {
|
||||||
|
reject(err);
|
||||||
|
};
|
||||||
|
reader.readAsText(blob);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取文件内容 返回 promise
|
* 读取文件内容 返回 promise
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
arrow-class="terminal-tooltip-content"
|
arrow-class="terminal-tooltip-content"
|
||||||
content="编辑内容">
|
content="编辑内容">
|
||||||
<a-button class="icon-button row-action-icon"
|
<a-button class="icon-button row-action-icon"
|
||||||
|
:disabled="editorLoading"
|
||||||
@click="editFile(record)">
|
@click="editFile(record)">
|
||||||
<icon-edit />
|
<icon-edit />
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -158,6 +159,7 @@
|
|||||||
session?: ISftpSession;
|
session?: ISftpSession;
|
||||||
list: Array<SftpFile>;
|
list: Array<SftpFile>;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
editorLoading: boolean;
|
||||||
selectedFiles: Array<string>;
|
selectedFiles: Array<string>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
:session="session"
|
:session="session"
|
||||||
:list="fileList"
|
:list="fileList"
|
||||||
:loading="tableLoading"
|
:loading="tableLoading"
|
||||||
|
:editor-loading="editorLoading"
|
||||||
@load-file="loadFiles"
|
@load-file="loadFiles"
|
||||||
@edit-file="editFile"
|
@edit-file="editFile"
|
||||||
@delete-file="deleteFile"
|
@delete-file="deleteFile"
|
||||||
@@ -70,6 +71,8 @@
|
|||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { openSftpCreateModalKey, openSftpMoveModalKey, openSftpChmodModalKey, openSftpUploadModalKey } from '../../types/const';
|
import { openSftpCreateModalKey, openSftpMoveModalKey, openSftpChmodModalKey, openSftpUploadModalKey } from '../../types/const';
|
||||||
|
import { getSftpFileContent, setSftpFileContent } from '@/api/asset/host-sftp';
|
||||||
|
import { isString } from '@/utils/is';
|
||||||
import SftpTableHeader from './sftp-table-header.vue';
|
import SftpTableHeader from './sftp-table-header.vue';
|
||||||
import SftpTable from './sftp-table.vue';
|
import SftpTable from './sftp-table.vue';
|
||||||
import SftpEditorHeader from './sftp-editor-header.vue';
|
import SftpEditorHeader from './sftp-editor-header.vue';
|
||||||
@@ -135,8 +138,7 @@
|
|||||||
// 编辑器保存
|
// 编辑器保存
|
||||||
const editorSave = () => {
|
const editorSave = () => {
|
||||||
setEditorLoading(true);
|
setEditorLoading(true);
|
||||||
const value = editorRef.value?.getValue() || '';
|
session.value?.setContent(editorFilePath.value);
|
||||||
session.value?.setContent(editorFilePath.value, value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭编辑器
|
// 关闭编辑器
|
||||||
@@ -231,24 +233,47 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 接收获取文件内容响应
|
// 接收获取文件内容响应
|
||||||
const resolveSftpGetContent = (path: string, result: string, msg: string, content: string) => {
|
const resolveSftpGetContent = (result: string, msg: string, token: string) => {
|
||||||
setTableLoading(false);
|
setTableLoading(false);
|
||||||
setEditorLoading(false);
|
setEditorLoading(false);
|
||||||
// 检查结果
|
// 检查结果
|
||||||
if (!checkResult(result, msg)) {
|
if (!checkResult(result, msg)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
editorRef.value?.setValue(content);
|
setEditorLoading(true);
|
||||||
|
editorRef.value?.setValue('');
|
||||||
|
// 读取文件
|
||||||
|
getSftpFileContent(token).then(async ({ data }) => {
|
||||||
|
if (isString(data)) {
|
||||||
|
// 成功为 string
|
||||||
|
editorRef.value?.setValue(data || '');
|
||||||
|
} else {
|
||||||
|
// 失败为 object
|
||||||
|
Message.error((data as any).msg || '读取失败');
|
||||||
|
}
|
||||||
|
setEditorLoading(false);
|
||||||
|
}).catch(() => {
|
||||||
|
setEditorLoading(false);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 接收修改文件内容响应
|
// 接收修改文件内容响应
|
||||||
const resolveSftpSetContent = (result: string, msg: string) => {
|
const resolveSftpSetContent = (result: string, msg: string, token: string) => {
|
||||||
setEditorLoading(false);
|
setEditorLoading(false);
|
||||||
// 检查结果
|
// 检查结果
|
||||||
if (!checkResult(result, msg)) {
|
if (!checkResult(result, msg)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Message.success('保存成功');
|
setEditorLoading(true);
|
||||||
|
// 获取文本
|
||||||
|
const value = editorRef.value?.getValue() || '';
|
||||||
|
// 保存
|
||||||
|
setSftpFileContent(token, value).then(() => {
|
||||||
|
setEditorLoading(false);
|
||||||
|
Message.success('保存成功');
|
||||||
|
}).catch(() => {
|
||||||
|
setEditorLoading(false);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 接收下载文件夹展开文件响应
|
// 接收下载文件夹展开文件响应
|
||||||
|
|||||||
@@ -144,11 +144,10 @@ export default class SftpSession extends BaseSession implements ISftpSession {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 修改内容
|
// 修改内容
|
||||||
setContent(path: string, content: string) {
|
setContent(path: string) {
|
||||||
this.channel.send(InputProtocol.SFTP_SET_CONTENT, {
|
this.channel.send(InputProtocol.SFTP_SET_CONTENT, {
|
||||||
sessionId: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
path,
|
path,
|
||||||
content
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -177,17 +177,17 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理 SFTP 获取文件内容
|
// 处理 SFTP 获取文件内容
|
||||||
processSftpGetContent({ sessionId, path, result, msg, content }: OutputPayload): void {
|
processSftpGetContent({ sessionId, result, msg, token }: OutputPayload): void {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
const session = this.sessionManager.getSession<ISftpSession>(sessionId);
|
const session = this.sessionManager.getSession<ISftpSession>(sessionId);
|
||||||
session && session.resolver.resolveSftpGetContent(path, result, msg, content);
|
session && session.resolver.resolveSftpGetContent(result, msg, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 SFTP 修改文件内容
|
// 处理 SFTP 修改文件内容
|
||||||
processSftpSetContent({ sessionId, result, msg }: OutputPayload) {
|
processSftpSetContent({ sessionId, result, msg, token }: OutputPayload) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
const session = this.sessionManager.getSession<ISftpSession>(sessionId);
|
const session = this.sessionManager.getSession<ISftpSession>(sessionId);
|
||||||
session && session.resolver.resolveSftpSetContent(result, msg);
|
session && session.resolver.resolveSftpSetContent(result, msg, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据类型处理操作
|
// 根据类型处理操作
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ export interface ISftpSession extends ITerminalSession {
|
|||||||
// 获取内容
|
// 获取内容
|
||||||
getContent: (path: string) => void;
|
getContent: (path: string) => void;
|
||||||
// 修改内容
|
// 修改内容
|
||||||
setContent: (path: string, content: string) => void;
|
setContent: (path: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sftp 会话接收器定义
|
// sftp 会话接收器定义
|
||||||
@@ -349,9 +349,9 @@ export interface ISftpSessionResolver {
|
|||||||
// 接收下载文件夹展开文件响应
|
// 接收下载文件夹展开文件响应
|
||||||
resolveDownloadFlatDirectory: (currentPath: string, result: string, msg: string, list: Array<SftpFile>) => void;
|
resolveDownloadFlatDirectory: (currentPath: string, result: string, msg: string, list: Array<SftpFile>) => void;
|
||||||
// 接收获取文件内容响应
|
// 接收获取文件内容响应
|
||||||
resolveSftpGetContent: (path: string, result: string, msg: string, content: string) => void;
|
resolveSftpGetContent: (result: string, msg: string, token: string) => void;
|
||||||
// 接收修改文件内容响应
|
// 接收修改文件内容响应
|
||||||
resolveSftpSetContent: (result: string, msg: string) => void;
|
resolveSftpSetContent: (result: string, msg: string, token: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sftp 文件
|
// sftp 文件
|
||||||
|
|||||||
Reference in New Issue
Block a user