- watcher握手期伪触发致幻影本地列表,根因修复 - 连接探测2.5s超时竞速,握手10s预算 - 30s保活自动掐死半开连接,取连接时剔除已断开 - 副本命名与进度计数抽公共,下载缓存清理去重
154 lines
5.2 KiB
Go
154 lines
5.2 KiB
Go
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)
|
|
}
|