feat: 为文件管理器添加右键“解/压缩”功能

Refs #28
This commit is contained in:
Baobhan Sith
2025-05-13 00:26:55 +08:00
parent 688b9df707
commit 52b797837e
18 changed files with 1126 additions and 82 deletions
+2 -2
View File
@@ -117,6 +117,8 @@ export function initializeConnectionHandler(wss: WebSocketServer, sshSuspendServ
case 'sftp:realpath':
case 'sftp:copy':
case 'sftp:move':
case 'sftp:compress':
case 'sftp:decompress':
await handleSftpOperation(ws, type, payload, requestId);
break;
@@ -132,8 +134,6 @@ export function initializeConnectionHandler(wss: WebSocketServer, sshSuspendServ
break;
// --- SSH Suspend Cases ---
// 旧的 SSH_SUSPEND_START 逻辑已被新的 SSH_MARK_FOR_SUSPEND 和 SshSuspendService.takeOverMarkedSession 取代
// case 'SSH_SUSPEND_START': { ... } // Removed
case 'SSH_SUSPEND_LIST_REQUEST': {
if (!ws.userId) {
@@ -84,6 +84,35 @@ export async function handleSftpOperation(
sftpService.move(sessionId, payload.sources, payload.destination, requestId);
} else throw new Error("Missing 'sources' (array) or 'destination' in payload for move");
break;
case 'sftp:compress':
if (Array.isArray(payload?.sources) && payload?.destination && payload?.format && requestId) {
const destinationPath = payload.destination as string;
// 从 destinationPath 中提取 targetDirectory 和 destinationArchiveName
// pathModule.posix 总是使用 / 作为分隔符
const pathModule = await import('path'); // 动态导入 path 模块
const targetDirectory = pathModule.posix.dirname(destinationPath);
const destinationArchiveName = pathModule.posix.basename(destinationPath);
const compressPayload = {
sources: payload.sources as string[],
destinationArchiveName: destinationArchiveName,
format: payload.format as 'zip' | 'targz' | 'tarbz2',
targetDirectory: targetDirectory,
requestId: requestId
};
sftpService.compress(sessionId, compressPayload);
} else throw new Error("Missing 'sources' (array), 'destination', 'format', or 'requestId' in payload for compress");
break;
case 'sftp:decompress':
if (payload?.source && requestId) {
const decompressPayload = {
archivePath: payload.source as string,
// destinationDirectory: payload.destination as string, // sftpService.decompress 目前不使用此参数
requestId: requestId
};
sftpService.decompress(sessionId, decompressPayload);
} else throw new Error("Missing 'source' or 'requestId' in payload for decompress");
break;
default:
console.warn(`WebSocket: Received unhandled SFTP message type in sftp.handler: ${type}`);
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'sftp_error', payload: { message: `内部未处理的 SFTP 类型: ${type}`, requestId } }));
+43 -1
View File
@@ -251,4 +251,46 @@ export type SshSuspendServerToClientMessages =
// export type WebSocketMessage = BaseMessageType | SshSuspendClientToServerMessages | OtherFeatureMessages;
// And for outgoing:
// export type WebSocketResponse = BaseResponseType | SshSuspendServerToClientMessages | OtherFeatureResponses;
// This part depends on the existing structure, so I'm providing the specific types for now.
// This part depends on the existing structure, so I'm providing the specific types for now.
// --- SFTP Compress/Decompress Message Types ---
// C -> S: Request to compress files/directories
export interface SftpCompressRequestPayload {
sources: string[]; // Array of source paths (relative to targetDirectory)
destinationArchiveName: string; // Desired name for the archive file
format: 'zip' | 'targz' | 'tarbz2'; // Archive format
targetDirectory: string; // The directory where sources are located and where the archive will be created
requestId: string;
}
// S -> C: Compression success
export interface SftpCompressSuccessPayload {
message: string;
requestId: string;
}
// S -> C: Compression error
export interface SftpCompressErrorPayload {
error: string;
details?: string; // Stderr output or specific error details
requestId: string;
}
// C -> S: Request to decompress an archive
export interface SftpDecompressRequestPayload {
archivePath: string; // Full path to the archive file
requestId: string;
}
// S -> C: Decompression success
export interface SftpDecompressSuccessPayload {
message: string;
requestId: string;
}
// S -> C: Decompression error
export interface SftpDecompressErrorPayload {
error: string;
details?: string; // Stderr output or specific error details
requestId: string;
}
+1 -1
View File
@@ -44,7 +44,7 @@ export function initializeUpgradeHandler(
// 确保 ipAddress 不是 undefined 或空字符串,否则设为 'unknown'
ipAddress = ipAddress || 'unknown';
console.log(`[WebSocket Upgrade] Determined IP Address: ${ipAddress}`);
// --- 结束修改 ---
console.log(`WebSocket: 升级请求来自 IP: ${ipAddress}, Path: ${pathname}`); // 使用新获取的 ipAddress