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,
		})
	}
}
相关推荐
007php0072 分钟前
某大厂MySQL面试之SQL注入触点发现与SQLMap测试
数据库·python·sql·mysql·面试·职场和发展·golang
雨中散步撒哈拉25 分钟前
13、做中学 | 初一下期 Golang数组与切片
开发语言·后端·golang
0wioiw027 分钟前
Go基础(③Cobra)
开发语言·后端·golang
楼田莉子35 分钟前
C++算法专题学习:栈相关的算法
开发语言·c++·算法·leetcode
晨非辰40 分钟前
#C语言——刷题攻略:牛客编程入门训练(九):攻克 分支控制(三)、循环控制(一),轻松拿捏!
c语言·开发语言·经验分享·学习方法·visual studio
_oP_i1 小时前
Java 服务接口中解决跨域(CORS,Cross-Origin Resource Sharing)问题
java·开发语言
陈序猿(代码自用版)1 小时前
【考研C语言编程题】数组元素批量插入实现(含图示+三部曲拆解)
c语言·开发语言·考研
唐•苏凯1 小时前
ArcGIS Pro 遇到严重的应用程序错误而无法启动
开发语言·javascript·ecmascript
hmcjn(小何同学)1 小时前
轻松Linux-9.进程间通信
linux·运维·服务器·c++·bash
月光在发光2 小时前
19_内核模块挂载问题处理
linux·运维·服务器