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,
		})
	}
}
相关推荐
DARLING Zero two♡17 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
Gu Gu Study20 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
芊寻(嵌入式)42 分钟前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
荒Huang1 小时前
Linux挖矿病毒(kswapd0进程使cpu爆满)
linux·运维·服务器
一颗松鼠1 小时前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
有梦想的咸鱼_1 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
海阔天空_20131 小时前
Python pyautogui库:自动化操作的强大工具
运维·开发语言·python·青少年编程·自动化
天下皆白_唯我独黑1 小时前
php 使用qrcode制作二维码图片
开发语言·php
夜雨翦春韭1 小时前
Java中的动态代理
java·开发语言·aop·动态代理
小远yyds1 小时前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js