golang实现从服务器下载文件到本地指定目录

一、连接服务器,采用sftp连接模式

go 复制代码
package middlewares

import (
	"fmt"
	"time"

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

// 建立服务器连接
func Connect(user, password, host string, port int) (*sftp.Client, error) {
	var (
		auth         []ssh.AuthMethod
		addr         string
		clientConfig *ssh.ClientConfig
		sshClient    *ssh.Client
		sftpClient   *sftp.Client
		err          error
	)
	// get auth method
	auth = make([]ssh.AuthMethod, 0)
	auth = append(auth, ssh.Password(password))
	clientConfig = &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{ssh.Password(password)},
		// 此处忽略了密钥认证,改用密码认证
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout:         30 * time.Second,
	}
	// 通过ssh连接到服务器
	addr = fmt.Sprintf("%s:%d", host, port)
	if sshClient, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
		return nil, err
	}
	// 创建一个sftp连接工具用来读取文件或者目录
	if sftpClient, err = sftp.NewClient(sshClient); err != nil {
		return nil, err
	}
	return sftpClient, nil
}

二、下载文件

go 复制代码
// 定义下载功能
func SyncCiticLog(r *gin.Context) {
	// viper设置的连接服务器的用户名和密码以及端口、连接的IP地址,此用户名写在了配置文件中
	User := viper.GetString("ConnectUser")
	Password := viper.GetString("ConnectPassword")
	Port := viper.GetInt("ConnectPort")
	citicIp := viper.GetString("ConnectOldIp")
	// 此处设置了要读取的目录前缀
	const allDir = "D:\\backup\\citic"
	// 定义变量用来接收下载文件的源目录和目标目录
	dstDir := ""
	srcDir := ""
	// 实例化结构体用来接收数据
	downloglist := DownLogList{}
	// 调用定义的sftp方法连接服务器
	sftpClient, sftpErr := middlewares.Connect(User, Password, citicIp, Port)
	// 此处要关闭要用defer关闭连接,否则下载的文件将发生打开文件错误
	defer sftpClient.Close()
	// 判断连接是否成功
	if sftpErr != nil {
		logs.Error(map[string]interface{}{"msg": sftpErr}, "未连接到服务器,请检查相关配置!")
	}
	// 此处用的Post请求,在请求体获取前端传递过来的参数
	if error := r.ShouldBindBodyWithJSON(&downloglist); error != nil {
		logs.Error(map[string]interface{}{"msg": "绑定结构体失败"}, "请检查配置文件是否正确!")
	} else {
		// 判断传递过来的IP,来定义相应的源目录和目标目录
		switch downloglist.ServiceIp {
		case "172.16.2.51":
			srcDir = "/home/backup/zqyl-abc/new"
			dstDir = "D:\\backup\\abc"
			break
		case "172.16.2.58":
			srcDir = "/home/backup/citic/" + downloglist.ServiceIp
			dstDir = filepath.Join(allDir, "中信03")
			break
		case "172.16.2.59":
			srcDir = "/home/backup/citic/" + downloglist.ServiceIp
			dstDir = filepath.Join(allDir, "中信04")
			break
		case "172.16.2.60":
			srcDir = "/home/backup/citic/" + downloglist.ServiceIp
			dstDir = filepath.Join(allDir, "中信01")
			break
		case "172.16.2.61":
			srcDir = "/home/backup/citic/" + downloglist.ServiceIp
			dstDir = filepath.Join(allDir, "中信02")
			break
		}
		// 由于传递过来的下载文件是多个,所以将以集合的形式传递过来,循环遍历来将单个文件进行下载
		for _, citicLog := range downloglist.LogList {
			// 拼出源文件的位置目录
			fileSrcDir := srcDir + "/" + citicLog
			// 利用sftp连接工具将文件目录打开
			openFile, err := sftpClient.Open(fileSrcDir)
			if err != nil {
				logs.Error(map[string]interface{}{"msg": "读取文件失败!"}, "请检查文件是否存在或者是否正常!")
			}
			// 创建本地文件存放的目录
			error := os.MkdirAll(dstDir, 0755)
			if error != nil {
				logs.Error(map[string]interface{}{"msg": "创建文件失败!"}, "请检查目录是否存在!")
			}
			// 创建本地文件的等待拷贝
			logFile, _ := os.Create(dstDir + "\\" + citicLog)
			// 创建资源记得关闭
			defer logFile.Close()
			// 拷贝文件至目标目录
			_, copyErr := io.Copy(logFile, openFile)
			if copyErr != nil {
				logs.Info(map[string]interface{}{"msg": "下载文件失败,请检查磁盘分区是否存在或者是否可写入状态!!"}, "")
			}
		}
		// 返回给前端状态码、下载成功信息、目标文件下载到的目录
		r.JSON(http.StatusOK, gin.H{
			"status":  http.StatusOK,
			"message": "下载成功!",
			"path":    dstDir,
		})
	}
}
相关推荐
慕y2747 分钟前
Java学习第九十三部分——RestTemplate
java·开发语言·学习
上单带刀不带妹9 分钟前
JavaScript 中的宏任务与微任务
开发语言·前端·javascript·ecmascript·宏任务·微任务
旋风菠萝10 分钟前
设计模式---单例
android·java·开发语言
啊呦.超能力19 分钟前
QT开发---图形与图像(补充)
开发语言·qt
郝学胜-神的一滴31 分钟前
应用Builder模式在C++中进行复杂对象构建
开发语言·c++·程序人生
微露清风37 分钟前
C语言习题讲解-第九讲- 常见错误分类等
c语言·开发语言
寄思~1 小时前
学习笔记:封装和单继承
开发语言·笔记·python·学习
归云鹤1 小时前
C++ 构造函数语义学
开发语言·c++
AI视觉网奇1 小时前
whisper tokenizer
linux·运维·服务器
E_ICEBLUE1 小时前
Python 操作 Word 文档:主流库对比与选择指南
开发语言·经验分享·python·word·办公自动化