package main import ( "fmt" "path" "path/filepath" "strconv" "strings" "time" "u-desk/internal/filesystem" "u-desk/internal/sftp" ) // ========== SFTP 接口 ========== func (a *App) ensureSftpService() *sftp.Service { a.mu.Lock() defer a.mu.Unlock() if a.sftpService == nil { a.sftpService = sftp.NewService() } return a.sftpService } // SftpConnect 建立 SFTP 连接,返回连接标识符 connID func (a *App) SftpConnect(req SftpConnectRequest) (string, error) { config := &sftp.Config{ Host: req.Host, Port: req.Port, Username: req.Username, Password: req.Password, KeyPath: req.KeyPath, KeyPassphrase: req.KeyPassphrase, } if config.Port == 0 { config.Port = 22 } if config.Timeout == 0 { config.Timeout = 15 * time.Second } svc := a.ensureSftpService() _, err := svc.GetManager().Connect(config) if err != nil { return "", sftp.ToUserMessage(err) } connID := sftp.ConnID(config.Host, config.Port) return connID, nil } // SftpDisconnect 断开 SFTP 连接 func (a *App) SftpDisconnect(connID string) error { parts := strings.SplitN(connID, ":", 2) if len(parts) < 2 { return fmt.Errorf("无效的连接标识符") } host := parts[0] port, err := strconv.Atoi(parts[1]) if err != nil { return fmt.Errorf("无效的端口号") } sftp.GetManager().Disconnect(host, port) return nil } // SftpListDir SFTP 列出目录 func (a *App) SftpListDir(connID string, dirPath string) ([]map[string]interface{}, error) { return a.ensureSftpService().ListDir(connID, dirPath) } // SftpReadFile SFTP 读取文件内容 func (a *App) SftpReadFile(connID string, filePath string) (string, error) { return a.ensureSftpService().ReadFile(connID, filePath) } // SftpWriteFile SFTP 写入文件 func (a *App) SftpWriteFile(req SftpWriteFileRequest) error { return a.ensureSftpService().WriteFile(req.SessionID, req.Path, req.Content) } // SftpWriteBase64File SFTP 写入 base64 编码的二进制文件(粘贴图片等) func (a *App) SftpWriteBase64File(sessionID, filePath, base64Content string) error { return a.ensureSftpService().WriteBase64File(sessionID, filePath, base64Content) } // SftpGetFileInfo SFTP 获取文件信息 func (a *App) SftpGetFileInfo(connID string, filePath string) (map[string]interface{}, error) { return a.ensureSftpService().GetFileInfo(connID, filePath) } // SftpCreateDir SFTP 创建目录 func (a *App) SftpCreateDir(connID string, dirPath string) (*filesystem.FileOperationResult, error) { return a.ensureSftpService().CreateDir(connID, dirPath) } // SftpCreateFile SFTP 创建文件 func (a *App) SftpCreateFile(connID string, filePath string) (*filesystem.FileOperationResult, error) { return a.ensureSftpService().CreateFile(connID, filePath) } // SftpDeletePath SFTP 删除文件或目录 func (a *App) SftpDeletePath(connID string, filePath string) (*filesystem.FileOperationResult, error) { return a.ensureSftpService().DeletePath(connID, filePath) } // SftpRenamePath SFTP 重命名文件或目录 func (a *App) SftpRenamePath(req SftpRenamePathRequest) (*filesystem.FileOperationResult, error) { return a.ensureSftpService().RenamePath(req.SessionID, req.OldPath, req.NewPath) } // SftpDownloadToTemp 下载远程文件到本地临时目录(用于预览) func (a *App) SftpDownloadToTemp(connID string, remotePath string) (string, error) { return a.ensureSftpService().DownloadToTemp(connID, remotePath) } // SftpDownloadSiteForPreview 下载 HTML 及其网站资源到本地临时目录 func (a *App) SftpDownloadSiteForPreview(connID string, remotePath string) (string, error) { return a.ensureSftpService().DownloadSiteForPreview(connID, remotePath) } // SftpDownloadToTempCached 带缓存的 SFTP 下载(命中缓存直接返回本地路径) func (a *App) SftpDownloadToTempCached(connID string, remotePath string, fileSize int64, modTime string) (string, error) { return a.ensureSftpService().DownloadToTempCached(connID, remotePath, fileSize, modTime) } // SftpDownloadToFile 下载远程文件/目录到用户指定目录(流式无上限,重名自动副本),返回本地落地路径 func (a *App) SftpDownloadToFile(connID string, remotePath string, localDstDir string) (string, error) { emitter := newTransferEmitter(a, "download", path.Base(remotePath)) localPath, err := a.ensureSftpService().DownloadToFile(connID, remotePath, localDstDir, emitter.progress) emitter.finish(err) return localPath, err } // SftpUploadFromFile 上传本地文件/目录到远程目录(流式,目录递归,重名自动副本) func (a *App) SftpUploadFromFile(connID string, localPath string, remoteDir string) error { emitter := newTransferEmitter(a, "upload", filepath.Base(localPath)) err := a.ensureSftpService().UploadFromFile(connID, localPath, remoteDir, emitter.progress) emitter.finish(err) return err } // SftpGetCommonPaths 获取 SFTP 远程主机常用路径 func (a *App) SftpGetCommonPaths(connID string) (map[string]string, error) { return a.ensureSftpService().GetCommonPaths(connID) } // SftpGetSystemInfo 获取 SFTP 远程主机系统信息(CPU/内存/磁盘) func (a *App) SftpGetSystemInfo(connID string) (map[string]interface{}, error) { return a.ensureSftpService().GetSystemInfo(connID) }