⚡ 优化文件上传逻辑.
This commit is contained in:
@@ -29,6 +29,14 @@
|
||||
:options="toOptions(sshOsTypeKey)"
|
||||
placeholder="请选择系统类型" />
|
||||
</a-form-item>
|
||||
<!-- SSH 端口 -->
|
||||
<a-form-item field="port"
|
||||
label="SSH端口"
|
||||
:hide-asterisk="true">
|
||||
<a-input-number v-model="formModel.port"
|
||||
placeholder="请输入SSH端口"
|
||||
hide-button />
|
||||
</a-form-item>
|
||||
<!-- 用户名 -->
|
||||
<a-form-item field="username"
|
||||
label="用户名"
|
||||
@@ -38,14 +46,6 @@
|
||||
:disabled="SshAuthType.IDENTITY === formModel.authType"
|
||||
placeholder="请输入用户名" />
|
||||
</a-form-item>
|
||||
<!-- SSH 端口 -->
|
||||
<a-form-item field="port"
|
||||
label="SSH端口"
|
||||
:hide-asterisk="true">
|
||||
<a-input-number v-model="formModel.port"
|
||||
placeholder="请输入SSH端口"
|
||||
hide-button />
|
||||
</a-form-item>
|
||||
<!-- 验证方式 -->
|
||||
<a-form-item field="authType"
|
||||
label="验证方式"
|
||||
|
||||
@@ -187,6 +187,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.arco-upload-list-item-name-link) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.arco-upload-list-item-name-text) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
</div>
|
||||
<!-- 进度 -->
|
||||
<a-tooltip position="left"
|
||||
:content="((file.current || 0) / file.fileSize * 100).toFixed(2) + '%'"
|
||||
:content="file.fileSize ? ((file.current || 0) / file.fileSize * 100).toFixed(2) + '%' : '0%'"
|
||||
mini>
|
||||
<a-progress type="circle"
|
||||
size="mini"
|
||||
:status="getDictValue(fileStatusKey, file.status, 'status') as any"
|
||||
:percent="(file.current || 0) / file.fileSize" />
|
||||
:percent="file.fileSize ? (file.current || 0) / file.fileSize : 0" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,41 +1,33 @@
|
||||
import type { ISftpTransferDownloader, SftpTransferItem } from '../types/terminal.type';
|
||||
import { TransferOperatorType, TransferStatus } from '../types/terminal.const';
|
||||
import { getFileName, getPath } from '@/utils/file';
|
||||
import type { SftpTransferItem } from '../types/terminal.type';
|
||||
import { TransferStatus, TransferType } from '../types/terminal.const';
|
||||
import { getFileName, openDownloadFile } from '@/utils/file';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { getDownloadTransferUrl } from '@/api/asset/host-sftp';
|
||||
import SftpTransferHandler from './sftp-transfer-handler';
|
||||
|
||||
// sftp 下载器实现
|
||||
export default class SftpTransferDownloader implements ISftpTransferDownloader {
|
||||
|
||||
public abort: boolean;
|
||||
|
||||
private client: WebSocket;
|
||||
private item: SftpTransferItem;
|
||||
export default class SftpTransferDownloader extends SftpTransferHandler {
|
||||
|
||||
constructor(item: SftpTransferItem, client: WebSocket) {
|
||||
this.abort = false;
|
||||
this.item = item;
|
||||
this.client = client;
|
||||
super(TransferType.DOWNLOAD, item, client);
|
||||
}
|
||||
|
||||
// 开始下载
|
||||
initDownload() {
|
||||
this.item.status = TransferStatus.TRANSFERRING;
|
||||
// 发送开始下载信息
|
||||
this.client?.send(JSON.stringify({
|
||||
type: TransferOperatorType.DOWNLOAD_INIT,
|
||||
path: getPath(this.item.parentPath + '/' + this.item.name),
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
// 开始回调
|
||||
onStart(channelId: string, token: string) {
|
||||
super.onStart(channelId, token);
|
||||
// 获取下载 url
|
||||
const url = getDownloadTransferUrl(channelId, token);
|
||||
// 打开
|
||||
openDownloadFile(url);
|
||||
}
|
||||
|
||||
// 下载完成
|
||||
downloadFinish() {
|
||||
if (this.abort) {
|
||||
// 完成回调
|
||||
onFinish() {
|
||||
super.onFinish();
|
||||
if (this.aborted) {
|
||||
// 中断则不触发下载
|
||||
return;
|
||||
}
|
||||
// 设置实际大小
|
||||
this.item.currentSize = this.item.totalSize;
|
||||
if (this.item.totalSize === 0) {
|
||||
// 空文件直接触发下载
|
||||
try {
|
||||
@@ -53,20 +45,4 @@ export default class SftpTransferDownloader implements ISftpTransferDownloader {
|
||||
}
|
||||
}
|
||||
|
||||
// 下载失败
|
||||
downloadError(msg: string | undefined) {
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
this.item.errorMessage = msg || '下载失败';
|
||||
}
|
||||
|
||||
// 下载中断
|
||||
downloadAbort() {
|
||||
this.abort = true;
|
||||
// 发送下载中断信息
|
||||
this.client?.send(JSON.stringify({
|
||||
type: TransferOperatorType.DOWNLOAD_ABORT,
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
import type { ISftpTransferHandler, SftpTransferItem } from '../types/terminal.type';
|
||||
import { TransferOperator, TransferStatus } from '../types/terminal.const';
|
||||
import { getPath } from '@/utils/file';
|
||||
|
||||
// sftp 传输处理器定义
|
||||
export default abstract class SftpTransferHandler implements ISftpTransferHandler {
|
||||
|
||||
public type: string;
|
||||
public finished: boolean;
|
||||
public aborted: boolean;
|
||||
protected client: WebSocket;
|
||||
protected item: SftpTransferItem;
|
||||
|
||||
protected constructor(type: string, item: SftpTransferItem, client: WebSocket) {
|
||||
this.type = type;
|
||||
this.finished = false;
|
||||
this.aborted = false;
|
||||
this.item = item;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
// 开始
|
||||
start() {
|
||||
this.item.status = TransferStatus.TRANSFERRING;
|
||||
// 发送开始信息
|
||||
this.client?.send(JSON.stringify({
|
||||
operator: TransferOperator.START,
|
||||
type: this.type,
|
||||
path: getPath(this.item.parentPath + '/' + this.item.name),
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
};
|
||||
|
||||
// 完成
|
||||
finish() {
|
||||
this.finished = true;
|
||||
this.item.status = TransferStatus.SUCCESS;
|
||||
// 发送完成的信息
|
||||
this.client?.send(JSON.stringify({
|
||||
operator: TransferOperator.FINISH,
|
||||
type: this.type,
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
};
|
||||
|
||||
// 失败
|
||||
error() {
|
||||
this.finished = true;
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
// 发送上传失败的信息
|
||||
this.client?.send(JSON.stringify({
|
||||
operator: TransferOperator.ERROR,
|
||||
type: this.type,
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
};
|
||||
|
||||
// 中断
|
||||
abort() {
|
||||
this.aborted = true;
|
||||
// 发送中断的信息
|
||||
this.client?.send(JSON.stringify({
|
||||
operator: TransferOperator.ABORT,
|
||||
type: this.type,
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
}
|
||||
|
||||
// 是否有下一个分片
|
||||
hasNextPart() {
|
||||
return false;
|
||||
};
|
||||
|
||||
// 下一页分片回调
|
||||
onNextPart() {
|
||||
return undefined as unknown as any;
|
||||
};
|
||||
|
||||
// 开始回调
|
||||
onStart(channelId: string, token: string) {
|
||||
};
|
||||
|
||||
// 进度回调
|
||||
onProgress(size: number) {
|
||||
if (this.item && size) {
|
||||
this.item.currentSize = size;
|
||||
}
|
||||
};
|
||||
|
||||
// 失败回调
|
||||
onError(msg: string | undefined) {
|
||||
this.finished = true;
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
this.item.errorMessage = msg || '传输失败';
|
||||
}
|
||||
|
||||
// 完成回调
|
||||
onFinish() {
|
||||
this.finished = true;
|
||||
this.item.status = TransferStatus.SUCCESS;
|
||||
this.item.currentSize = this.item.totalSize;
|
||||
};
|
||||
|
||||
// 中断回调
|
||||
onAbort() {
|
||||
this.aborted = true;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
import type { ISftpTransferManager, ISftpTransferUploader, SftpTransferItem } from '../types/terminal.type';
|
||||
import { ISftpTransferDownloader, SftpFile, TransferOperatorResponse } from '../types/terminal.type';
|
||||
import { sessionCloseMsg, TransferReceiverType, TransferStatus, TransferType } from '../types/terminal.const';
|
||||
import type { ISftpTransferHandler, ISftpTransferManager, SftpFile, SftpTransferItem, TransferOperatorResponse } from '../types/terminal.type';
|
||||
import { sessionCloseMsg, TransferReceiver, TransferStatus, TransferType } from '../types/terminal.const';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { getTerminalAccessToken, openHostTransferChannel } from '@/api/asset/host-terminal';
|
||||
import { nextId } from '@/utils';
|
||||
import { getDownloadTransferUrl } from '@/api/asset/host-sftp';
|
||||
import SftpTransferUploader from './sftp-transfer-uploader';
|
||||
import SftpTransferDownloader from './sftp-transfer-downloader';
|
||||
import { openDownloadFile } from '@/utils/file';
|
||||
|
||||
// sftp 传输管理器实现
|
||||
export default class SftpTransferManager implements ISftpTransferManager {
|
||||
@@ -20,9 +17,7 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
|
||||
private currentItem?: SftpTransferItem;
|
||||
|
||||
private currentUploader?: ISftpTransferUploader;
|
||||
|
||||
private currentDownloader?: ISftpTransferDownloader;
|
||||
private currentTransfer?: ISftpTransferHandler;
|
||||
|
||||
public transferList: Array<SftpTransferItem>;
|
||||
|
||||
@@ -57,13 +52,14 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
|
||||
// 添加下载任务
|
||||
addDownload(hostId: number, currentPath: string, files: Array<SftpFile>) {
|
||||
let pathIndex = currentPath === '/' ? 1 : currentPath.length + 1;
|
||||
// 转为下载文件
|
||||
const items = files.map(s => {
|
||||
return {
|
||||
fileId: nextId(10),
|
||||
type: TransferType.DOWNLOAD,
|
||||
hostId: hostId,
|
||||
name: s.path.substring(currentPath.length + 1),
|
||||
name: s.path.substring(pathIndex),
|
||||
parentPath: currentPath,
|
||||
currentSize: 0,
|
||||
totalSize: s.size,
|
||||
@@ -87,11 +83,7 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
const item = this.transferList[index];
|
||||
if (item.status === TransferStatus.TRANSFERRING) {
|
||||
// 传输中则中断传输
|
||||
if (this.currentUploader) {
|
||||
this.currentUploader.uploadAbort();
|
||||
} else if (this.currentDownloader) {
|
||||
this.currentDownloader.downloadAbort();
|
||||
}
|
||||
this.currentTransfer?.abort();
|
||||
}
|
||||
// 从列表中移除
|
||||
this.transferList.splice(index, 1);
|
||||
@@ -154,8 +146,7 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
|
||||
// 传输下一条任务
|
||||
private transferNextItem() {
|
||||
this.currentUploader = undefined;
|
||||
this.currentDownloader = undefined;
|
||||
this.currentTransfer = undefined;
|
||||
// 释放内存
|
||||
if (this.currentItem) {
|
||||
this.currentItem.file = null as unknown as File;
|
||||
@@ -163,14 +154,15 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
// 获取任务
|
||||
this.currentItem = this.transferList.find(s => s.status === TransferStatus.WAITING);
|
||||
if (this.currentItem) {
|
||||
// 开始传输
|
||||
if (this.currentItem.type === TransferType.UPLOAD) {
|
||||
// 上传
|
||||
this.uploadFile();
|
||||
this.currentTransfer = new SftpTransferUploader(this.currentItem, this.client as WebSocket);
|
||||
} else {
|
||||
// 下载
|
||||
this.downloadFile();
|
||||
this.currentTransfer = new SftpTransferDownloader(this.currentItem, this.client as WebSocket);
|
||||
}
|
||||
// 开始
|
||||
this.currentTransfer?.start();
|
||||
} else {
|
||||
// 无任务关闭会话
|
||||
this.client?.close();
|
||||
@@ -181,110 +173,33 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
private async resolveMessage(message: MessageEvent) {
|
||||
// 文本消息
|
||||
const data = JSON.parse(message.data) as TransferOperatorResponse;
|
||||
if (data.type === TransferReceiverType.NEXT_TRANSFER
|
||||
|| data.type === TransferReceiverType.UPLOAD_FINISH
|
||||
|| data.type === TransferReceiverType.UPLOAD_ERROR) {
|
||||
// 执行下一个传输任务
|
||||
this.resolveNextTransfer(data);
|
||||
} else if (data.type === TransferReceiverType.UPLOAD_NEXT_BLOCK) {
|
||||
// 接收下一块上传数据
|
||||
await this.resolveUploadNextBlock();
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_START) {
|
||||
// 开始下载
|
||||
this.resolveDownloadStart(data);
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_PROGRESS) {
|
||||
// 下载进度
|
||||
this.resolveDownloadProgress(data);
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_FINISH) {
|
||||
// 下载完成
|
||||
this.resolveDownloadFinish();
|
||||
} else if (data.type === TransferReceiverType.DOWNLOAD_ERROR) {
|
||||
// 下载失败
|
||||
this.resolveDownloadError(data.msg);
|
||||
if (data.type === TransferReceiver.NEXT_PART) {
|
||||
// 接收下一块数据回调
|
||||
await this.currentTransfer?.onNextPart();
|
||||
} else if (data.type === TransferReceiver.START) {
|
||||
// 开始回调
|
||||
this.currentTransfer?.onStart(data.channelId as string, data.transferToken as string);
|
||||
} else if (data.type === TransferReceiver.PROGRESS) {
|
||||
// 进度回调
|
||||
this.currentTransfer?.onProgress(data.currentSize as number);
|
||||
} else if (data.type === TransferReceiver.FINISH) {
|
||||
// 完成回调
|
||||
this.currentTransfer?.onFinish();
|
||||
// 开始下一个传输任务
|
||||
this.transferNextItem();
|
||||
} else if (data.type === TransferReceiver.ERROR) {
|
||||
// 失败回调
|
||||
this.currentTransfer?.onError(data.msg);
|
||||
// 开始下一个传输任务
|
||||
this.transferNextItem();
|
||||
} else if (data.type === TransferReceiver.ABORT) {
|
||||
// 中断回调
|
||||
this.currentTransfer?.onAbort();
|
||||
// 开始下一个传输任务
|
||||
this.transferNextItem();
|
||||
}
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
private uploadFile() {
|
||||
// 创建上传器
|
||||
this.currentUploader = new SftpTransferUploader(this.currentItem as SftpTransferItem, this.client as WebSocket);
|
||||
// 开始上传
|
||||
this.currentUploader.startUpload();
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
private downloadFile() {
|
||||
// 创建下载器
|
||||
this.currentDownloader = new SftpTransferDownloader(this.currentItem as SftpTransferItem, this.client as WebSocket);
|
||||
// 初始化下载
|
||||
this.currentDownloader.initDownload();
|
||||
}
|
||||
|
||||
// 接收下一个传输任务响应
|
||||
private resolveNextTransfer(data: TransferOperatorResponse) {
|
||||
if (this.currentItem) {
|
||||
if (data.success) {
|
||||
this.currentItem.status = TransferStatus.SUCCESS;
|
||||
} else {
|
||||
this.currentItem.status = TransferStatus.ERROR;
|
||||
this.currentItem.errorMessage = data.msg || '传输失败';
|
||||
}
|
||||
}
|
||||
// 开始下一个传输任务
|
||||
this.transferNextItem();
|
||||
}
|
||||
|
||||
// 接收下一块上传数据响应
|
||||
private async resolveUploadNextBlock() {
|
||||
// 只可能为上传并且成功
|
||||
if (!this.currentUploader) {
|
||||
return;
|
||||
}
|
||||
if (this.currentUploader.hasNextBlock()
|
||||
&& !this.currentUploader.abort
|
||||
&& !this.currentUploader.finish) {
|
||||
try {
|
||||
// 有下一个分片则上传 (上一个分片传输完成)
|
||||
await this.currentUploader.uploadNextBlock();
|
||||
} catch (e) {
|
||||
// 读取文件失败
|
||||
this.currentUploader.uploadError((e as Error).message);
|
||||
}
|
||||
} else {
|
||||
// 没有下一个分片则发送完成
|
||||
this.currentUploader.uploadFinish();
|
||||
}
|
||||
}
|
||||
|
||||
// 接收开始下载响应
|
||||
private resolveDownloadStart(data: TransferOperatorResponse) {
|
||||
// 获取下载 url
|
||||
const url = getDownloadTransferUrl(data.channelId as string, data.transferToken as string);
|
||||
// 打开
|
||||
openDownloadFile(url);
|
||||
}
|
||||
|
||||
// 接收下载进度响应
|
||||
private resolveDownloadProgress(data: TransferOperatorResponse) {
|
||||
if (this.currentItem && data.currentSize) {
|
||||
this.currentItem.currentSize = data.currentSize;
|
||||
}
|
||||
}
|
||||
|
||||
// 接收下载完成响应
|
||||
private resolveDownloadFinish() {
|
||||
this.currentDownloader?.downloadFinish();
|
||||
// 开始下一个传输任务
|
||||
this.transferNextItem();
|
||||
}
|
||||
|
||||
// 接收下载失败响应
|
||||
private resolveDownloadError(msg: string | undefined) {
|
||||
this.currentDownloader?.downloadError(msg);
|
||||
// 开始下一个传输任务
|
||||
this.transferNextItem();
|
||||
}
|
||||
|
||||
// 关闭 释放资源
|
||||
private close() {
|
||||
// 重置 run
|
||||
|
||||
@@ -1,52 +1,54 @@
|
||||
import type { ISftpTransferUploader, SftpTransferItem } from '../types/terminal.type';
|
||||
import { TransferOperatorType, TransferStatus } from '../types/terminal.const';
|
||||
import { getPath } from '@/utils/file';
|
||||
import type { SftpTransferItem } from '../types/terminal.type';
|
||||
import { TransferType } from '../types/terminal.const';
|
||||
import SftpTransferHandler from './sftp-transfer-handler';
|
||||
|
||||
// 512 KB
|
||||
export const BLOCK_SIZE = 512 * 1024;
|
||||
export const PART_SIZE = 512 * 1024;
|
||||
|
||||
// sftp 上传器实现
|
||||
export default class SftpTransferUploader implements ISftpTransferUploader {
|
||||
export default class SftpTransferUploader extends SftpTransferHandler {
|
||||
|
||||
public finish: boolean;
|
||||
public abort: boolean;
|
||||
private currentBlock: number;
|
||||
private totalBlock: number;
|
||||
private client: WebSocket;
|
||||
private item: SftpTransferItem;
|
||||
private currentPart: number;
|
||||
private readonly totalPart: number;
|
||||
private file: File;
|
||||
|
||||
constructor(item: SftpTransferItem, client: WebSocket) {
|
||||
this.abort = false;
|
||||
this.finish = false;
|
||||
this.item = item;
|
||||
this.client = client;
|
||||
super(TransferType.UPLOAD, item, client);
|
||||
this.file = item.file;
|
||||
this.currentBlock = 0;
|
||||
this.totalBlock = Math.ceil(item.file.size / BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// 开始上传
|
||||
startUpload() {
|
||||
this.item.status = TransferStatus.TRANSFERRING;
|
||||
// 发送开始上传信息
|
||||
this.client?.send(JSON.stringify({
|
||||
type: TransferOperatorType.UPLOAD_START,
|
||||
path: getPath(this.item.parentPath + '/' + this.item.name),
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
this.currentPart = 0;
|
||||
this.totalPart = Math.ceil(item.file.size / PART_SIZE);
|
||||
}
|
||||
|
||||
// 是否有下一个分片
|
||||
hasNextBlock() {
|
||||
return this.currentBlock < this.totalBlock;
|
||||
hasNextPart() {
|
||||
return this.currentPart < this.totalPart;
|
||||
}
|
||||
|
||||
// 上传下一个分片
|
||||
async uploadNextBlock() {
|
||||
async onNextPart() {
|
||||
super.onNextPart();
|
||||
// 完成或者中断直接跳过
|
||||
if (this.aborted || this.finished) {
|
||||
return;
|
||||
}
|
||||
if (this.hasNextPart()) {
|
||||
try {
|
||||
// 有下一个分片则上传
|
||||
await this.doUploadNextPart();
|
||||
} catch (e) {
|
||||
// 读取文件失败
|
||||
this.error();
|
||||
}
|
||||
} else {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// 执行上传下一分片
|
||||
private async doUploadNextPart() {
|
||||
// 读取数据
|
||||
const start = this.currentBlock * BLOCK_SIZE;
|
||||
const end = Math.min(this.file.size, start + BLOCK_SIZE);
|
||||
const start = this.currentPart * PART_SIZE;
|
||||
const end = Math.min(this.file.size, start + PART_SIZE);
|
||||
const chunk = this.file.slice(start, end);
|
||||
const reader = new FileReader();
|
||||
const arrayBuffer = await new Promise((resolve, reject) => {
|
||||
@@ -56,36 +58,8 @@ export default class SftpTransferUploader implements ISftpTransferUploader {
|
||||
});
|
||||
// 发送数据
|
||||
this.client?.send(arrayBuffer as ArrayBuffer);
|
||||
this.currentBlock++;
|
||||
this.currentPart++;
|
||||
this.item.currentSize += (end - start);
|
||||
}
|
||||
|
||||
// 上传完成
|
||||
uploadFinish() {
|
||||
this.finish = true;
|
||||
this.item.status = TransferStatus.SUCCESS;
|
||||
// 发送上传完成的信息
|
||||
this.client?.send(JSON.stringify({
|
||||
type: TransferOperatorType.UPLOAD_FINISH,
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
}
|
||||
|
||||
// 上传失败
|
||||
uploadError(msg: string | undefined) {
|
||||
this.finish = true;
|
||||
this.item.status = TransferStatus.ERROR;
|
||||
this.item.errorMessage = msg || '上传失败';
|
||||
// 发送上传完成的信息
|
||||
this.client?.send(JSON.stringify({
|
||||
type: TransferOperatorType.UPLOAD_ERROR,
|
||||
hostId: this.item.hostId
|
||||
}));
|
||||
}
|
||||
|
||||
// 上传中断
|
||||
uploadAbort() {
|
||||
this.abort = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {
|
||||
import type {
|
||||
ISftpSession,
|
||||
ISshSession,
|
||||
ITerminalChannel,
|
||||
@@ -76,7 +76,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
||||
ssh.connect();
|
||||
} else {
|
||||
// 未成功展示错误信息
|
||||
ssh.write(`[91m${msg || ''}\r\n输入回车重新连接...[0m\r\n\r\n`);
|
||||
ssh.write(`[91m${msg || ''}[0m\r\n[91m输入回车重新连接...[0m\r\n\r\n`);
|
||||
ssh.status = TerminalStatus.CLOSED;
|
||||
}
|
||||
}, sftp => {
|
||||
@@ -109,7 +109,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
||||
// ssh 拼接关闭消息
|
||||
ssh.write(`\r\n\r\n[91m${msg || ''}[0m\r\n`);
|
||||
if (!isForceClose) {
|
||||
ssh.write('[91m输入回车重新连接...[0m\r\n\r\n');
|
||||
ssh.write(`[91m${msg || ''}[0m\r\n[91m输入回车重新连接...[0m\r\n\r\n`);
|
||||
}
|
||||
// 设置状态
|
||||
ssh.status = TerminalStatus.CLOSED;
|
||||
|
||||
@@ -327,25 +327,22 @@ export const TransferType = {
|
||||
DOWNLOAD: 'download'
|
||||
};
|
||||
|
||||
// 传输操作类型
|
||||
export const TransferOperatorType = {
|
||||
UPLOAD_START: 'uploadStart',
|
||||
UPLOAD_FINISH: 'uploadFinish',
|
||||
UPLOAD_ERROR: 'uploadError',
|
||||
DOWNLOAD_INIT: 'downloadInit',
|
||||
DOWNLOAD_ABORT: 'downloadAbort',
|
||||
// 传输操作
|
||||
export const TransferOperator = {
|
||||
START: 'start',
|
||||
FINISH: 'finish',
|
||||
ERROR: 'error',
|
||||
ABORT: 'abort',
|
||||
};
|
||||
|
||||
// 传输响应类型
|
||||
export const TransferReceiverType = {
|
||||
NEXT_TRANSFER: 'nextTransfer',
|
||||
UPLOAD_NEXT_BLOCK: 'uploadNextBlock',
|
||||
UPLOAD_FINISH: 'uploadFinish',
|
||||
UPLOAD_ERROR: 'uploadError',
|
||||
DOWNLOAD_START: 'downloadStart',
|
||||
DOWNLOAD_PROGRESS: 'downloadProgress',
|
||||
DOWNLOAD_FINISH: 'downloadFinish',
|
||||
DOWNLOAD_ERROR: 'downloadError',
|
||||
// 传输响应
|
||||
export const TransferReceiver = {
|
||||
NEXT_PART: 'nextPart',
|
||||
START: 'start',
|
||||
PROGRESS: 'progress',
|
||||
FINISH: 'finish',
|
||||
ERROR: 'error',
|
||||
ABORT: 'abort',
|
||||
};
|
||||
|
||||
// 会话关闭信息
|
||||
|
||||
@@ -414,38 +414,41 @@ export interface ISftpTransferManager {
|
||||
cancelAllTransfer: () => void;
|
||||
}
|
||||
|
||||
// sftp 上传器定义
|
||||
export interface ISftpTransferUploader {
|
||||
// 是否完成
|
||||
finish: boolean;
|
||||
// 是否中断
|
||||
abort: boolean;
|
||||
// 开始上传
|
||||
startUpload: () => void;
|
||||
// 是否有下一个分片
|
||||
hasNextBlock: () => boolean;
|
||||
// 上传下一个分片
|
||||
uploadNextBlock: () => Promise<void>;
|
||||
// 上传完成
|
||||
uploadFinish: () => void;
|
||||
// 上传失败
|
||||
uploadError: (msg: string | undefined) => void;
|
||||
// 上传中断
|
||||
uploadAbort: () => void;
|
||||
|
||||
// sftp 传输处理回调定义
|
||||
export interface ISftpTransferCallback {
|
||||
// 下一分片回调
|
||||
onNextPart: () => Promise<void>;
|
||||
// 开始回调
|
||||
onStart: (channelId: string, token: string) => void;
|
||||
// 进度回调
|
||||
onProgress: (size: number) => void;
|
||||
// 失败回调
|
||||
onError: (msg: string | undefined) => void;
|
||||
// 完成回调
|
||||
onFinish: () => void;
|
||||
// 中断回调
|
||||
onAbort: () => void;
|
||||
}
|
||||
|
||||
// sftp 下载器定义
|
||||
export interface ISftpTransferDownloader {
|
||||
// sftp 传输处理器定义
|
||||
export interface ISftpTransferHandler extends ISftpTransferCallback {
|
||||
// 类型
|
||||
type: string;
|
||||
// 是否完成
|
||||
finished: boolean;
|
||||
// 是否中断
|
||||
abort: boolean;
|
||||
// 初始化下载
|
||||
initDownload: () => void;
|
||||
// 下载完成
|
||||
downloadFinish: () => void;
|
||||
// 下载失败
|
||||
downloadError: (msg: string | undefined) => void;
|
||||
// 下载中断
|
||||
downloadAbort: () => void;
|
||||
aborted: boolean;
|
||||
// 开始
|
||||
start: () => void;
|
||||
// 完成
|
||||
finish: () => void;
|
||||
// 失败
|
||||
error: () => void;
|
||||
// 中断
|
||||
abort: () => void;
|
||||
// 是否有下一个分片
|
||||
hasNextPart: () => boolean;
|
||||
}
|
||||
|
||||
// sftp 上传文件项
|
||||
|
||||
Reference in New Issue
Block a user