diff --git a/orion-visor-ui/src/views/terminal/service/session/rdp-session.ts b/orion-visor-ui/src/views/terminal/service/session/rdp-session.ts index 8e063769..93033afd 100644 --- a/orion-visor-ui/src/views/terminal/service/session/rdp-session.ts +++ b/orion-visor-ui/src/views/terminal/service/session/rdp-session.ts @@ -1,15 +1,15 @@ import type { - GuacdInitConfig, - GuacdReactiveSessionStatus, IGuacdChannel, IRdpSession, - IRdpSessionClipboardHandler, + TerminalSessionTabItem, + GuacdInitConfig, IRdpSessionDisplayHandler, - TerminalSessionTabItem + GuacdReactiveSessionStatus, + IRdpSessionClipboardHandler } from '@/views/terminal/interfaces'; import type { OutputPayload } from '@/views/terminal/types/protocol'; import { InputProtocol } from '@/views/terminal/types/protocol'; -import { fitDisplayValue, TerminalCloseCode, TerminalMessages } from '@/views/terminal/types/const'; +import { TerminalMessages, fitDisplayValue, TerminalCloseCode } from '@/views/terminal/types/const'; import { screenshot } from '@/views/terminal/types/utils'; import { useTerminalStore } from '@/store'; import Guacamole from 'guacamole-common-js'; @@ -25,6 +25,8 @@ export const CONNECT_TIMEOUT = 10000; // RDP 会话实现 export default class RdpSession extends BaseSession implements IRdpSession { + public fileSystemName: string; + public config: GuacdInitConfig; public client: Guacamole.Client; @@ -40,6 +42,7 @@ export default class RdpSession extends BaseSession { + if (fileSystemName) { + this.fileSystemName = fileSystemName; + } + }; + // 下载文件回调 + this.client.onfile = (stream, mimetype, filename) => { + useTerminalStore().transferManager.rdp.addDownload(this, stream, mimetype, filename); + }; } // 连接会话 @@ -209,6 +220,14 @@ export default class RdpSession extends BaseSession this.onProgress(undefined, len); + // 结束回调 + this.reader.onend = this.onFinish.bind(this); + } catch (e) { + this.onError(TerminalMessages.fileTransferError); + } + } + + // 进度发生变化 + onProgress(_: number | undefined, currentSize: number | undefined): void { + if (this.state.aborted || this.state.finished) { + return; + } + // 设置进度 + this.state.totalSize += currentSize || 0; + this.state.currentSize += currentSize || 0; + // 发送 ACK + if (this.stream) { + this.stream.sendAck('Received', Guacamole.Status.Code.SUCCESS); + } + } + + // 完成回调 + onFinish(): void { + if (this.state.aborted || this.state.finished) { + return; + } + this.state.finished = true; + this.state.progress = 100; + this.state.status = TransferStatus.SUCCESS; + // 完成下载文件 + const blob = this.reader.getBlob(); + saveAs(blob, this.fileItem.name); + // 释放资源 + this.releaseResource(); + } + + // 下载终端回调 + onAbort(): void { + if (this.state.aborted || this.state.finished) { + return; + } + this.state.aborted = true; + try { + if (this.session.status.connected) { + if (this.stream) { + // 发送 ACK + this.stream.sendAck('Aborted', Guacamole.Status.Code.RESOURCE_CLOSED); + // 关闭流 + this.session.client.endStream(this.stream.index); + } + } + // 触发失败 + this.onError(TerminalMessages.sessionClosed); + } catch (e) { + // 触发失败 + this.onError(TerminalMessages.fileTransferError); + } + } + + // 下载失败回调 + onError(msg: string | undefined): void { + this.state.finished = true; + this.state.status = TransferStatus.ERROR; + this.state.errorMessage = msg || TerminalMessages.fileTransferError; + // 释放资源 + this.releaseResource(); + } + + // 释放资源 + private releaseResource() { + if (this.stream) { + this.stream.onend = null; + this.stream.onblob = null; + } + this.stream = undefined as unknown as Guacamole.InputStream; + this.reader = undefined as unknown as Guacamole.BlobReader; + } + +} diff --git a/orion-visor-ui/src/views/terminal/service/transfer/terminal-transfer-manager.ts b/orion-visor-ui/src/views/terminal/service/transfer/terminal-transfer-manager.ts new file mode 100644 index 00000000..79f78797 --- /dev/null +++ b/orion-visor-ui/src/views/terminal/service/transfer/terminal-transfer-manager.ts @@ -0,0 +1,17 @@ +import type { ITerminalTransferManager, IRdpTransferManager, ISftpTransferManager } from '@/views/terminal/interfaces'; +import SftpTransferManager from './sftp-transfer-manager'; +import RdpTransferManager from './rdp-transfer-manager'; + +// 传输管理器基类 +export default class TerminalTransferManager implements ITerminalTransferManager { + + public sftp: ISftpTransferManager; + + public rdp: IRdpTransferManager; + + constructor() { + this.sftp = new SftpTransferManager(); + this.rdp = new RdpTransferManager(); + } + +}