使用Golang从SFTP服务器下载所有文件的方法

使用Golang从SFTP服务器下载所有文件的方法 你好

如何从SFTP服务器下载所有文件?

6 回复

这里有一个很好的教程:如何使用 Go 连接 SFTP

更多关于使用Golang从SFTP服务器下载所有文件的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


是的,但不行,因为那样做需要列出所有文件,而使用这个方法无法递归列出SFTP服务器上的所有文件。

那么你的意思是你需要递归地处理子目录吗?如果是这样,请检查 listFiles 函数,当遇到目录时,只需再次调用该函数并传入当前目录的名称。

func main() {
    fmt.Println("hello world")
}

我认为我们需要你提供更多细节,以及你目前已经尝试过的方法。

例如:我想连接到包含文件 a、aa、ab、aaa、di 以及 do pz 文件夹的服务器 a,并通过我的 Go 脚本下载所有这些文件。

你好,

我认为我们需要你提供更多细节,以及你目前已经尝试过的方法。

你可以查看 sftp 包 及其示例。

可以使用 github.com/pkg/sftp 包配合 golang.org/x/crypto/ssh 包来实现从SFTP服务器批量下载文件。以下是完整的示例代码:

package main

import (
    "fmt"
    "io"
    "os"
    "path/filepath"
    "time"

    "golang.org/x/crypto/ssh"
    "github.com/pkg/sftp"
)

func downloadAllFilesFromSFTP(host, user, password, remoteDir, localDir string) error {
    // SSH客户端配置
    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
        Timeout:         30 * time.Second,
    }

    // 连接到SSH服务器
    conn, err := ssh.Dial("tcp", host+":22", config)
    if err != nil {
        return fmt.Errorf("SSH连接失败: %v", err)
    }
    defer conn.Close()

    // 创建SFTP客户端
    client, err := sftp.NewClient(conn)
    if err != nil {
        return fmt.Errorf("SFTP客户端创建失败: %v", err)
    }
    defer client.Close()

    // 获取远程目录下的所有文件
    files, err := client.ReadDir(remoteDir)
    if err != nil {
        return fmt.Errorf("读取远程目录失败: %v", err)
    }

    // 确保本地目录存在
    if err := os.MkdirAll(localDir, 0755); err != nil {
        return fmt.Errorf("创建本地目录失败: %v", err)
    }

    // 遍历并下载所有文件
    for _, file := range files {
        if file.IsDir() {
            continue // 跳过子目录,只下载文件
        }

        remotePath := filepath.Join(remoteDir, file.Name())
        localPath := filepath.Join(localDir, file.Name())

        // 打开远程文件
        remoteFile, err := client.Open(remotePath)
        if err != nil {
            fmt.Printf("打开远程文件 %s 失败: %v\n", remotePath, err)
            continue
        }

        // 创建本地文件
        localFile, err := os.Create(localPath)
        if err != nil {
            remoteFile.Close()
            fmt.Printf("创建本地文件 %s 失败: %v\n", localPath, err)
            continue
        }

        // 复制文件内容
        _, err = io.Copy(localFile, remoteFile)
        remoteFile.Close()
        localFile.Close()

        if err != nil {
            fmt.Printf("下载文件 %s 失败: %v\n", remotePath, err)
            os.Remove(localPath) // 删除不完整的文件
        } else {
            fmt.Printf("成功下载: %s -> %s\n", remotePath, localPath)
        }
    }

    return nil
}

func main() {
    // 使用示例
    err := downloadAllFilesFromSFTP(
        "sftp.example.com",
        "username",
        "password",
        "/remote/path",
        "./local/downloads",
    )
    
    if err != nil {
        fmt.Printf("下载失败: %v\n", err)
    } else {
        fmt.Println("所有文件下载完成")
    }
}

如果需要包含子目录的递归下载,可以使用以下递归版本:

func downloadRecursive(client *sftp.Client, remotePath, localPath string) error {
    // 获取远程文件信息
    info, err := client.Stat(remotePath)
    if err != nil {
        return err
    }

    if info.IsDir() {
        // 创建本地目录
        if err := os.MkdirAll(localPath, 0755); err != nil {
            return err
        }

        // 读取目录内容
        files, err := client.ReadDir(remotePath)
        if err != nil {
            return err
        }

        // 递归处理每个项目
        for _, file := range files {
            remoteFilePath := filepath.Join(remotePath, file.Name())
            localFilePath := filepath.Join(localPath, file.Name())
            if err := downloadRecursive(client, remoteFilePath, localFilePath); err != nil {
                return err
            }
        }
    } else {
        // 下载单个文件
        remoteFile, err := client.Open(remotePath)
        if err != nil {
            return err
        }
        defer remoteFile.Close()

        localFile, err := os.Create(localPath)
        if err != nil {
            return err
        }
        defer localFile.Close()

        if _, err := io.Copy(localFile, remoteFile); err != nil {
            return err
        }
    }
    return nil
}

使用前需要安装依赖:

go get golang.org/x/crypto/ssh
go get github.com/pkg/sftp

这个实现包含了错误处理、连接管理和文件传输的基本功能。

回到顶部