Python实现SFTP下载

Python实现SFTP下载

上节课讲了通过SFTP软件连接Linux远程下载上传文件。但是,人生苦短,我用python。

基础知识

为什么要用python呢?因为我之前一直用的Fillezilla出现了bug,远程搜索不能搜索文件了,然后我就了解到python也可以实现SSH和SFTP连接,通过编程也能减少重复性的操作。

  1. paramiko 是python的一个库。通过paramiko我们可以在Python代码中直接使用SSH协议对远程服务器执行操作,而无须通过ssh命令对远程服务器进行操作。
  2. paramiko包含两个核心组件:SSHClientSFTPClient
  3. SSHClient的作用类似于Linux的ssh命令,是对SSH会话的封装,该类封装了传输(Transport),通道(Channel)及SFTPClient建立的方法(open_sftp),通常用于执行远程命令。
  4. SFTPClient的作用类似与Linux的sftp命令,是对SFTP客户端的封装,用以实现远程文件操作,如文件上传、下载、修改文件权限等操作
  5. ftplib是封装了FTP方法和类的库,这里不做过多介绍。
  6. python环境建议使用Anaconda下的juyter,开源软件,自行百度安装。

paramiko的安装

如果用的是idle环境,需要在cmd里面安装paramiko库。
win+R → cmd

pip install paramiko

如果装了Anaconda,paramiko和ftplib都是自带的库,直接import即可。

SFTP连接

话不多说,直接上代码

import paramiko
 
# 获取Transport实例
tran = paramiko.Transport(('10.0.0.3', 22))
# 连接SSH服务端,使用password
tran.connect(username="root", password='123456')
# 获取SFTP实例
sftp = paramiko.SFTPClient.from_transport(tran)
#put(localpath, remotepath, callback=None, confirm=True) 将本地文件上传到服务器 参数confirm:是否调用stat()方法检查文件状态,返回ls -l的结果
#get(remotepath, localpath, callback=None) 从服务器下载文件到本地
#mkdir() 在服务器上创建目录
#remove() 在服务器上删除目录
#rename() 在服务器上重命名目录
#stat() 查看服务器文件状态
#listdir() 列出服务器目录下的文件
#用完记得关了
tran.close()

SFTP下载

import paramiko
import os
#from pathlib import Path
import stat

def DownLoadFileTree(LocalDir, RemoteDir):  # 下载整个目录下的文件或文件夹
    host="192.168.7.191"                                #sftp ip
    port=22                                             #sftp端口 
    sf = paramiko.Transport((host, port))
    sf.connect(username="name" , password="123456" )
    sftp = paramiko.SFTPClient.from_transport(sf)
    if not os.path.exists(LocalDir):
        os.makedirs(LocalDir)
    files = sftp.listdir_attr(RemoteDir)
    for file in files:
        if stat.S_ISDIR(file.st_mode):#是否为linux形式目录 true 目录 false 文件
            Local = os.path.join(LocalDir, file.filename)
            Remote = os.path.join(RemoteDir, file.filename)+"/"
            if not os.path.exists(Local):
                 os.makedirs(Local)
            # print("ok")
            DownLoadFileTree(host, port, username, password, Local, Remote)
        else:  # 文件
            Local = os.path.join(LocalDir, file.filename)
            Remote = RemoteDir+'/'+ file.filename
            #print(Remote,'->',Local)
            sftp.get(Remote,Local)
    sf.close()

把get方法改为put方法,即可类似的实现文件的上传操作。

put(localpath, remotepath)

递归列出所有子目录

def myDir(remote,n=0):
	host="192.168.7.191"              #sftp ip
    port=22                           #sftp端口 
    sf = paramiko.Transport((host, port))
    sf.connect(username="name" , password="123456" )
    sftp = paramiko.SFTPClient.from_transport(sf)
    files = sftp.listdir_attr(remote)
    for file in files:
        if not stat.S_ISDIR(file.st_mode):
            print('\t'*n,file.filename) 
        else:
            print('\t'*n,file.filename+":")
            myDir(remote+"/"+file.filename,n+1)
    sf.close()

在列出了所有子目录及文件的基础上,可以添加代码筛选自己需要的文件进行下载。

附赠FTP方法

import os
import sys
import ftplib  # 定义了FTP类,实现ftp上传和下载
 
class myFtp:
    # 定义一个ftp对象
    ftp = ftplib.FTP()
 
    def __init__(self, host, port=21): # 类似c++构造函数
        self.ftp.connect(host, port)
 
    # 登陆
    def Login(self, user, passwd):
        self.ftp.login(user, passwd)
        print(self.ftp.welcome)  # 打印出欢迎信息
 
    # 下载单个文件
    # LocalFile为本地文件路径(带文件名),RemoteFile为ftp文件路径(不带文件名)
    def DownLoadFile(self,LocalFile,RemoteFile):
        if(os.path.exists(LocalFile)):
            os.remove(LocalFile)
        file_handler = open(LocalFile, 'wb')
        print(file_handler)
        # 下载ftp文件
        self.ftp.retrbinary('RETR ' + RemoteFile, file_handler.write)
        file_handler.close()
        return True
 
    # 下载整个目录下的文件
    # LocalDir为本地目录(不带文件名),RemoteDir为远程目录(不带文件名)
    def DownLoadFileTree(self, LocalDir, RemoteDir):
        print("RemoteDir:", RemoteDir)
        if not os.path.exists(LocalDir):
            os.makedirs(LocalDir)
        # 打开该远程目录
        self.ftp.cwd(RemoteDir)
        # 获取该目录下所有文件名,列表形式
        RemoteNames = self.ftp.nlst()
        for file in RemoteNames:
            Local = os.path.join(LocalDir, file)  # 下载到当地的全路径
            print(self.ftp.nlst(file))  # [如test.txt]
            if file.find(".") == -1:  #是否子目录 如test.txt就非子目录
                if not os.path.exists(Local):
                    os.makedirs(Local)
                self.DownLoadFileTree(Local, file)  # 下载子目录路径
            else:
                self.DownLoadFile(Local, file)
        self.ftp.cwd("..")  # 返回路径最外侧
        return
 
    # 关闭ftp连接
    def close(self):
        self.ftp.close()

总结

Filezilla虽然功能强大,但操作仍然有些繁琐。做测试的时候如果需要经常上传、下载、修改文件,还是建议使用python编程,一劳永逸。
好处就是可以下载具有复杂关系的文件,可以把多个线程的结果一并下载。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值