diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/HostSftpLogController.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/HostSftpLogController.java index 320781a8..91beda83 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/HostSftpLogController.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/controller/HostSftpLogController.java @@ -18,6 +18,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import javax.annotation.Resource; @@ -60,6 +61,24 @@ public class HostSftpLogController { 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 @IgnoreWrapper @IgnoreLog(IgnoreLogMode.RET) diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/define/cache/HostTerminalCacheKeyDefine.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/define/cache/HostTerminalCacheKeyDefine.java index 9ce86b12..3353b57e 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/define/cache/HostTerminalCacheKeyDefine.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/define/cache/HostTerminalCacheKeyDefine.java @@ -5,6 +5,8 @@ import com.orion.lang.define.cache.key.CacheKeyDefine; 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.HostTerminalTransferDTO; +import com.orion.visor.module.asset.entity.dto.SftpGetContentCacheDTO; +import com.orion.visor.module.asset.entity.dto.SftpSetContentCacheDTO; import java.util.concurrent.TimeUnit; @@ -33,4 +35,20 @@ public interface HostTerminalCacheKeyDefine { .timeout(3, TimeUnit.MINUTES) .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(); + } diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/entity/dto/SftpGetContentCacheDTO.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/entity/dto/SftpGetContentCacheDTO.java new file mode 100644 index 00000000..c515d905 --- /dev/null +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/entity/dto/SftpGetContentCacheDTO.java @@ -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; + +} diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/entity/dto/SftpSetContentCacheDTO.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/entity/dto/SftpSetContentCacheDTO.java new file mode 100644 index 00000000..ee72c039 --- /dev/null +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/entity/dto/SftpSetContentCacheDTO.java @@ -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; + +} diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/InputTypeEnum.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/InputTypeEnum.java index 7914f165..83f0b308 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/InputTypeEnum.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/InputTypeEnum.java @@ -159,8 +159,8 @@ public enum InputTypeEnum { */ SFTP_SET_CONTENT("sc", SftpSetContentHandler.class, - new String[]{"type", "sessionId", "path", "content"}, - SftpSetContentRequest.class, + new String[]{"type", "sessionId", "path"}, + SftpBaseRequest.class, true), ; diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/OutputTypeEnum.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/OutputTypeEnum.java index 413e56ca..4bb7c879 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/OutputTypeEnum.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/enums/OutputTypeEnum.java @@ -83,12 +83,12 @@ public enum OutputTypeEnum { /** * SFTP 获取文件内容 */ - SFTP_GET_CONTENT("gc", "${type}|${sessionId}|${path}|${result}|${msg}|${content}"), + SFTP_GET_CONTENT("gc", "${type}|${sessionId}|${result}|${msg}|${token}"), /** * SFTP 修改文件内容 */ - SFTP_SET_CONTENT("sc", "${type}|${sessionId}|${result}|${msg}"), + SFTP_SET_CONTENT("sc", "${type}|${sessionId}|${result}|${msg}|${token}"), ; diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/SftpGetContentHandler.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/SftpGetContentHandler.java index 1e376eca..0f1d6f41 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/SftpGetContentHandler.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/handler/SftpGetContentHandler.java @@ -1,7 +1,10 @@ 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.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.model.request.SftpBaseRequest; import com.orion.visor.module.asset.handler.host.terminal.model.response.SftpGetContentResponse; @@ -28,11 +31,18 @@ public class SftpGetContentHandler extends AbstractTerminalHandler { +public class SftpSetContentHandler extends AbstractTerminalHandler { @Override - public void handle(WebSocketSession channel, SftpSetContentRequest payload) { + public void handle(WebSocketSession channel, SftpBaseRequest payload) { long startTime = System.currentTimeMillis(); // 获取会话 String sessionId = payload.getSessionId(); ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId); String path = payload.getPath(); log.info("SftpSetContentHandler-handle start sessionId: {}, path: {}", sessionId, path); + String token = UUIds.random32(); Exception ex = null; - // 修改内容 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); } catch (Exception e) { log.error("SftpSetContentHandler-handle error sessionId: {}", sessionId, e); @@ -45,9 +57,10 @@ public class SftpSetContentHandler extends AbstractTerminalHandler - * i|eff00a1|path|content + * sftp 设置内容响应 * * @author Jiahang Li * @version 1.0.0 - * @since 2024/2/6 13:31 + * @since 2024/2/6 16:20 */ @Data @SuperBuilder @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = true) -public class SftpSetContentRequest extends SftpBaseRequest { +public class SftpSetContentResponse extends SftpBaseResponse { /** * content */ - private String content; + private String token; } diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/ISftpSession.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/ISftpSession.java index 5baa459a..c78722ac 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/ISftpSession.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/ISftpSession.java @@ -102,4 +102,11 @@ public interface ISftpSession extends ITerminalSession { */ void setContent(String path, String content); + /** + * 检测文件是否可编辑 + * + * @param path path + */ + void checkCanEdit(String path); + } diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/SftpSession.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/SftpSession.java index c33b1173..4ccc69e7 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/SftpSession.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/handler/host/terminal/session/SftpSession.java @@ -9,6 +9,7 @@ import com.orion.net.host.SessionStore; import com.orion.net.host.sftp.SftpExecutor; import com.orion.net.host.sftp.SftpFile; 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.module.asset.handler.host.terminal.model.TerminalConfig; 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 public void keepAlive() { try { diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/HostSftpService.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/HostSftpService.java index 6dd47ab5..ad073e65 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/HostSftpService.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/HostSftpService.java @@ -3,9 +3,11 @@ package com.orion.visor.module.asset.service; import com.orion.lang.define.wrapper.DataGrid; import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest; 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 javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; /** @@ -33,6 +35,24 @@ public interface HostSftpService { */ Integer deleteHostSftpLog(List 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 下载 * diff --git a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostSftpServiceImpl.java b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostSftpServiceImpl.java index 765982d6..2a972fa9 100644 --- a/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostSftpServiceImpl.java +++ b/orion-visor-module-asset/orion-visor-module-asset-service/src/main/java/com/orion/visor/module/asset/service/impl/HostSftpServiceImpl.java @@ -4,29 +4,47 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.orion.lang.constant.StandardContentType; 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.Exceptions; 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.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.common.constant.Const; import com.orion.visor.framework.common.constant.ErrorMessage; 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.define.cache.HostTerminalCacheKeyDefine; 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.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.session.DownloadSession; 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.entity.dto.operator.OperatorLogQueryDTO; import com.orion.web.servlet.web.Servlets; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.List; import java.util.Optional; @@ -47,6 +65,9 @@ public class HostSftpServiceImpl implements HostSftpService { @Resource private HostTransferManager hostTransferManager; + @Resource + private HostTerminalService hostTerminalService; + @Override public DataGrid getHostSftpLogPage(HostSftpLogQueryRequest request) { // 查询 @@ -78,6 +99,73 @@ public class HostSftpServiceImpl implements HostSftpService { 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 public StreamingResponseBody downloadWithTransferToken(String channelId, String transferToken, HttpServletResponse response) { // 获取会话 diff --git a/orion-visor-ui/src/api/asset/host-sftp.ts b/orion-visor-ui/src/api/asset/host-sftp.ts index 26e13c2a..ed0da178 100644 --- a/orion-visor-ui/src/api/asset/host-sftp.ts +++ b/orion-visor-ui/src/api/asset/host-sftp.ts @@ -63,10 +63,35 @@ export function deleteHostSftpLog(idList: Array) { }); } +/** + * 获取 SFTP 文件内容 + */ +export function getSftpFileContent(token: string) { + return axios.get('/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('/asset/host-sftp/set-content', formData, { + timeout: 60000, + headers: { + 'Content-Type': 'multipart/form-data' + } + }); +} + /** * 下载文件 */ export function getDownloadTransferUrl(channelId: string, transferToken: string) { return `${httpBaseUrl}/asset/host-sftp/download?channelId=${channelId}&transferToken=${transferToken}`; } - diff --git a/orion-visor-ui/src/types/protocol/terminal.protocol.ts b/orion-visor-ui/src/types/protocol/terminal.protocol.ts index 388ea341..3bb68430 100644 --- a/orion-visor-ui/src/types/protocol/terminal.protocol.ts +++ b/orion-visor-ui/src/types/protocol/terminal.protocol.ts @@ -100,7 +100,7 @@ export const InputProtocol = { // SFTP 修改内容 SFTP_SET_CONTENT: { type: 'sc', - template: ['type', 'sessionId', 'path', 'content'] + template: ['type', 'sessionId', 'path'] }, }; @@ -181,13 +181,13 @@ export const OutputProtocol = { // SFTP 获取文件内容 SFTP_GET_CONTENT: { type: 'gc', - template: ['type', 'sessionId', 'path', 'result', 'msg', 'content'], + template: ['type', 'sessionId', 'result', 'msg', 'token'], processMethod: 'processSftpGetContent' }, // SFTP 修改文件内容 SFTP_SET_CONTENT: { type: 'sc', - template: ['type', 'sessionId', 'result', 'msg'], + template: ['type', 'sessionId', 'result', 'msg', 'token'], processMethod: 'processSftpSetContent' }, }; diff --git a/orion-visor-ui/src/utils/file.ts b/orion-visor-ui/src/utils/file.ts index fb9d8173..ed1e1a7b 100644 --- a/orion-visor-ui/src/utils/file.ts +++ b/orion-visor-ui/src/utils/file.ts @@ -7,6 +7,22 @@ export function getBase64Data(e: string) { 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 */ diff --git a/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table.vue b/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table.vue index 3a2bf753..e48ae631 100644 --- a/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table.vue +++ b/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table.vue @@ -77,6 +77,7 @@ arrow-class="terminal-tooltip-content" content="编辑内容"> @@ -158,6 +159,7 @@ session?: ISftpSession; list: Array; loading: boolean; + editorLoading: boolean; selectedFiles: Array; }>(); diff --git a/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-view.vue b/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-view.vue index 9e5be2ef..ed7911f0 100644 --- a/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-view.vue +++ b/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-view.vue @@ -25,6 +25,7 @@ :session="session" :list="fileList" :loading="tableLoading" + :editor-loading="editorLoading" @load-file="loadFiles" @edit-file="editFile" @delete-file="deleteFile" @@ -70,6 +71,8 @@ import { Message } from '@arco-design/web-vue'; import useLoading from '@/hooks/loading'; 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 SftpTable from './sftp-table.vue'; import SftpEditorHeader from './sftp-editor-header.vue'; @@ -135,8 +138,7 @@ // 编辑器保存 const editorSave = () => { setEditorLoading(true); - const value = editorRef.value?.getValue() || ''; - session.value?.setContent(editorFilePath.value, value); + session.value?.setContent(editorFilePath.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); setEditorLoading(false); // 检查结果 if (!checkResult(result, msg)) { 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); // 检查结果 if (!checkResult(result, msg)) { return; } - Message.success('保存成功'); + setEditorLoading(true); + // 获取文本 + const value = editorRef.value?.getValue() || ''; + // 保存 + setSftpFileContent(token, value).then(() => { + setEditorLoading(false); + Message.success('保存成功'); + }).catch(() => { + setEditorLoading(false); + }); }; // 接收下载文件夹展开文件响应 diff --git a/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts b/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts index 811b7c67..8cc499d8 100644 --- a/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts +++ b/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts @@ -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, { sessionId: this.sessionId, path, - content }); }; diff --git a/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts b/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts index 9b792c83..aa5a4c4b 100644 --- a/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts +++ b/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts @@ -177,17 +177,17 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor } // 处理 SFTP 获取文件内容 - processSftpGetContent({ sessionId, path, result, msg, content }: OutputPayload): void { + processSftpGetContent({ sessionId, result, msg, token }: OutputPayload): void { // 获取会话 const session = this.sessionManager.getSession(sessionId); - session && session.resolver.resolveSftpGetContent(path, result, msg, content); + session && session.resolver.resolveSftpGetContent(result, msg, token); } // 处理 SFTP 修改文件内容 - processSftpSetContent({ sessionId, result, msg }: OutputPayload) { + processSftpSetContent({ sessionId, result, msg, token }: OutputPayload) { // 获取会话 const session = this.sessionManager.getSession(sessionId); - session && session.resolver.resolveSftpSetContent(result, msg); + session && session.resolver.resolveSftpSetContent(result, msg, token); } // 根据类型处理操作 diff --git a/orion-visor-ui/src/views/host/terminal/types/define.ts b/orion-visor-ui/src/views/host/terminal/types/define.ts index 4c550935..26147972 100644 --- a/orion-visor-ui/src/views/host/terminal/types/define.ts +++ b/orion-visor-ui/src/views/host/terminal/types/define.ts @@ -323,7 +323,7 @@ export interface ISftpSession extends ITerminalSession { // 获取内容 getContent: (path: string) => void; // 修改内容 - setContent: (path: string, content: string) => void; + setContent: (path: string) => void; } // sftp 会话接收器定义 @@ -349,9 +349,9 @@ export interface ISftpSessionResolver { // 接收下载文件夹展开文件响应 resolveDownloadFlatDirectory: (currentPath: string, result: string, msg: string, list: Array) => 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 文件