Golang FTP文件下载实现方案
在Golang中实现FTP文件下载时,使用标准库还是第三方库更合适?有没有推荐的稳定库?需要注意哪些常见问题,比如断点续传、连接超时或大文件下载的性能优化?能否提供一个简单的代码示例?
2 回复
在Golang中实现FTP文件下载,可以通过标准库net/ftp来完成。以下是完整的实现方案:
核心代码实现
package main
import (
"fmt"
"io"
"net/ftp"
"os"
"path/filepath"
"time"
)
// FTPClient 封装FTP客户端
type FTPClient struct {
client *ftp.ServerConn
}
// NewFTPClient 创建FTP客户端连接
func NewFTPClient(host, user, password string, port int) (*FTPClient, error) {
addr := fmt.Sprintf("%s:%d", host, port)
conn, err := ftp.Dial(addr, ftp.DialWithTimeout(30*time.Second))
if err != nil {
return nil, fmt.Errorf("连接FTP服务器失败: %v", err)
}
err = conn.Login(user, password)
if err != nil {
return nil, fmt.Errorf("FTP登录失败: %v", err)
}
return &FTPClient{client: conn}, nil
}
// DownloadFile 下载单个文件
func (fc *FTPClient) DownloadFile(remotePath, localPath string) error {
// 创建本地目录
dir := filepath.Dir(localPath)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("创建本地目录失败: %v", err)
}
// 创建本地文件
localFile, err := os.Create(localPath)
if err != nil {
return fmt.Errorf("创建本地文件失败: %v", err)
}
defer localFile.Close()
// 从FTP服务器读取文件
reader, err := fc.client.Retr(remotePath)
if err != nil {
return fmt.Errorf("读取远程文件失败: %v", err)
}
defer reader.Close()
// 复制文件内容
_, err = io.Copy(localFile, reader)
if err != nil {
return fmt.Errorf("下载文件失败: %v", err)
}
fmt.Printf("文件下载成功: %s -> %s\n", remotePath, localPath)
return nil
}
// Close 关闭连接
func (fc *FTPClient) Close() error {
if fc.client != nil {
return fc.client.Quit()
}
return nil
}
// 使用示例
func main() {
// 连接FTP服务器
client, err := NewFTPClient("ftp.example.com", "username", "password", 21)
if err != nil {
fmt.Printf("错误: %v\n", err)
return
}
defer client.Close()
// 下载文件
err = client.DownloadFile("/remote/path/file.txt", "./local/file.txt")
if err != nil {
fmt.Printf("下载失败: %v\n", err)
return
}
}
高级功能扩展
1. 批量下载文件
// DownloadMultipleFiles 批量下载文件
func (fc *FTPClient) DownloadMultipleFiles(fileMap map[string]string) error {
for remotePath, localPath := range fileMap {
if err := fc.DownloadFile(remotePath, localPath); err != nil {
return fmt.Errorf("下载 %s 失败: %v", remotePath, err)
}
}
return nil
}
2. 下载整个目录
// DownloadDirectory 下载整个目录
func (fc *FTPClient) DownloadDirectory(remoteDir, localDir string) error {
entries, err := fc.client.List(remoteDir)
if err != nil {
return err
}
for _, entry := range entries {
remotePath := remoteDir + "/" + entry.Name
localPath := filepath.Join(localDir, entry.Name)
if entry.Type == ftp.EntryTypeFolder {
// 递归下载子目录
fc.DownloadDirectory(remotePath, localPath)
} else {
// 下载文件
fc.DownloadFile(remotePath, localPath)
}
}
return nil
}
关键要点
- 连接管理: 使用
DialWithTimeout设置连接超时 - 错误处理: 对每个操作进行错误检查
- 资源清理: 使用defer确保连接和文件正确关闭
- 目录创建: 自动创建本地目录结构
这个方案提供了稳定可靠的FTP文件下载功能,可以根据实际需求进行扩展。


