Python 基于Python实现Ftp文件上传,下载

测试环境:

Ftp客户端:Windows平台

Ftp服务器:Linux平台

Python版本:Python 2.7.6

实现功能:

支持FTP文件上传、下载,可以上传目录(分区除外),也可以上传单个文件;可以下载整个目录(/根目录除外),也可以下载单个文件

实践代码:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
from ftplib import  FTP
import  ConfigParser
import os
class MyFTP:
    def __init__(self, ftp_conf):
        '''ftp服务器主机IP,端口等配置'''
        config = ConfigParser.ConfigParser()
        config.read(ftp_conf)
        self.ftp_host = config.get('FTP', 'ftp_host')
        self.ftp_port = config.get('FTP', 'ftp_port')
        self.ftp_user = config.get('FTP', 'ftp_user')
        self.ftp_passwd = config.get('FTP', 'ftp_passwd')
        self.ftp = FTP()
    def get_ftp_host(self):
        return self.ftp_host
    def get_ftp_port(self):
        return self.ftp_port
    def get_ftp_user(self):
        return self.ftp_user
    def get_ftp_passwd(self):
        return self.ftp_passwd
    # 连接到ftp服务器
    def connect(self):
        print('is connecting to ftp server %s on %s' % (self.ftp_host, self.ftp_port))
        self.ftp.connect(self.ftp_host, self.ftp_port)
    # 登陆到ftp服务器
    def login(self):
        print('ready to login ftp server')
        self.ftp.login(self.ftp_user, self.ftp_passwd)
        print('login ftp server successfully')
        print(self.ftp.getwelcome())
    # 友好的关闭连接
    def quit(self):
        try:
            self.ftp.quit()
            print('colose ftp connection successfully')
        except Exception as e:
            print('%s' % e)
    # 上传文件夹
    def upload_folder(self, local_path='../screenshot_lib', remote_path='/home/testacc'):
        if not os.path.isdir(local_path):
            print('出错了,请选择要上传的文件夹')
            return
        local_path = local_path.strip() # 以防万一,去除首尾空格
        local_path = local_path.rstrip('/') # 去除右部 /
        local_path = local_path.rstrip('\\') # 去除右部 \\
        remote_path = remote_path.strip()
        remote_path = remote_path.rstrip('/')
        remote_path = remote_path.rstrip('\\')
        self.ftp.cwd(remote_path)
        last_dir = os.path.basename(local_path)
        remote_path = os.path.join(remote_path, last_dir)
        remote_path = remote_path.replace('\\', '/') # 转为linux标准路径
        # 如果ftp服务器上不存在该路径,则创建对应路径下的目录
        try:
            self.ftp.mkd(last_dir)
        except:
            #print('dir: %s already exists' % last_dir)
            pass
        sub_items = os.listdir(local_path)
        for sub_item in sub_items:
            sub_item_path = os.path.join(local_path, sub_item)
            if os.path.isdir(sub_item_path): #如果子项目为目录
                self.upload_folder(sub_item_path, remote_path)
            else:
                self.upload_file(sub_item_path, remote_path)
    # 上传文件
    def upload_file(self, src_file_path, remote_path):
        remote_file_name = os.path.split(src_file_path)[1]
        remote_path = remote_path + '/' + remote_file_name
        try: #如果文件不存在,调用file.size(filename)会报错
            if self.ftp.size(remote_path) != None:
                print("文件%s已存在" % remote_path)
                return
        except Exception as e:
            pass
        with open(src_file_path, 'rb') as file_handler:
             self.ftp.storbinary('STOR %s' % remote_path , file_handler)
             print('文件:%s 已经上传到ftp' % src_file_path)
    # 下载目录
    def download_dir(self,local_path, remote_path):
        if os.path.isfile(local_path):
            print('出错了,请选择文件保存位置')
            return
        local_path = local_path.strip() # 以防万一,去除首尾空格
        remote_path = remote_path.strip()
        remote_path = remote_path.rstrip('/')
        remote_path = remote_path.rstrip('\\')
        last_dir = os.path.basename(remote_path)
        local_path = os.path.join(local_path, last_dir)
        local_path = local_path.replace('/', '\\') # 转为Windows标准路径
        # 如果本地客户端不存在该路径,则创建对应路径下的目录
        if not os.path.isdir(local_path):
            os.mkdir(local_path)
        sub_items = self.ftp.nlst(remote_path)
        for sub_item in sub_items:
            try:
                self.ftp.cwd(sub_item) #如果子项目为目录
                self.download_dir(local_path, sub_item)
            except Exception: # 非目录
                self.download_file(local_path, sub_item)
    def download_file(self, local_path, remote_file_path):

if os.path.isdir(local_file_path):

             print('请选择文件保存目录路径')

             return
        



        last_file_name = os.path.split(remote_file_path)[1]
        local_file_path = os.path.join(local_path, last_file_name)
        if os.path.isfile(local_file_path):
            local_file_path = local_file_path.replace('\\', '/')
            print('文件:%s 已存在' % local_file_path)
            return
        with open(local_file_path, 'wb') as file_handle:
            self.ftp.retrbinary('RETR %s' % remote_file_path, file_handle.write)
if __name__ == '__main__':
    ftp = MyFTP('./config/ftp.conf')
    ftp.connect()
    ftp.login()
    ftp.upload_folder()
    ftp.upload_folder('E:\\dir1')
    # ftp.upload_folder('E:\\dir1\\')
    # ftp.upload_folder('E:/dir1/')
    # ftp.download_dir('E:\\', '/home/testacc')
    # ftp.download_dir('E:/', '/home/testacc')
    ftp.download_file('E:\\', '/home/testacc/testfile')
    ftp.quit()
ftp.conf配置如下:
[FTP]
ftp_host = 192.168.1.103
ftp_port = 21
ftp_user = testacc
ftp_passwd = testacc

测试数据如下:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程创造城市

python中数字格式化输出,厉害了!

Decimal.Context(prec=3,rounding=ROUND_HALF_UP).create_decimal(string类型)返回正常的四舍五入...

47720
来自专栏自译文章/自学记录

pyenv virtualenv 理解

Screen Shot 2019-07-18 at 7.04.31 PM.png

13320
来自专栏自译文章/自学记录

Socket Programming in Python(Guide)

Sockets 和 socket API被用于在网络上发送消息。它们提供了进程间通信(IPC)的一种形式。而网络既可以是连接到计算机的本地网络,也可以是计算机被...

8620
来自专栏未闻Code

一日一技:使用doctest测试Python代码的注释

如果大家看过一些有名的Python开源项目,你可能会看到他们在文档型注释里面,出现了下面这样的使用示例:

9520
来自专栏自译文章/自学记录

Django配置流程

数据库设置 ENGINE: 指定所使用的是个什么样的数据库 NAME:指明 数据库的名称 USER:指示 数据库的用户名 PASSWOR...

8620
来自专栏FreeBuf

委内瑞拉军方遭受Machete组织攻击

Machete是一个由西班牙语组织开发的网络间谍工具集,自2010年以来一直处于活动之中。该组织持续为其恶意软件开发新功能。他们长期攻击的重点在拉丁美洲国家,多...

10220
来自专栏编程创造城市

python中四舍五入,颠覆你的想象

上一节知识点主要讲到了进制转换,这一块其实属于计算机基础课程。在Python中主要涉及到:

9130
来自专栏自译文章/自学记录

新建Django项目遇到的问题

问题大概出在第4部,使用了该目录~/pyprj/mooc。大概是因为在该目录下有个.python-version文件,文件内容是virtual-env-3.6....

10340
来自专栏编程创造城市

python中序列解包特性及其便捷赋值,人生苦短,我学python

上一节我们学习了print函数,对其做了深入理解,这个系统输出函数其实有两个参数功能非常强大,分别是sep参数用于分隔符;end参数,结尾文本内容的修改。

15730
来自专栏机器之心

在Win上做Python开发?当然是用官方的MS Terminal和VS Code了

使用 Windows 系统一大好处是它的应用太丰富了,甚至强大的 GPU 也能在闲暇时间做点其它「工作」。然而与 Linux 或 macOS 不同,在 Wind...

14920

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励