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,
		})
	}
}
相关推荐
black0moonlight1 小时前
ISAAC Gym 7. 使用箭头进行数据可视化
开发语言·python
时光の尘1 小时前
C语言菜鸟入门·关键字·int的用法
c语言·开发语言·数据结构·c++·单片机·链表·c
坊钰1 小时前
【Java 数据结构】时间和空间复杂度
java·开发语言·数据结构·学习·算法
Edward-tan1 小时前
c语言数据结构与算法--简单实现线性表(顺序表+链表)的插入与删除
c语言·开发语言·链表
武昌库里写JAVA1 小时前
一文读懂Redis6的--bigkeys选项源码以及redis-bigkey-online项目介绍
c语言·开发语言·数据结构·算法·二维数组
苹果酱05672 小时前
windows安装redis, 修改自启动的redis服务的密码
java·开发语言·spring boot·mysql·中间件
学习使我飞升2 小时前
OSPF路由状态数据库、type 类型、完整的LSA
服务器·网络·智能路由器
学习使我飞升2 小时前
spf算法、三类LSA、区间防环路机制/规则、虚连接
服务器·网络·算法·智能路由器
hgdlip2 小时前
重装系统后ip地址错误,网络无法接通怎么办
服务器·网络协议·tcp/ip·重装系统
蒟蒻的贤2 小时前
vue11.22
开发语言·前端·javascript