Python操作FTP服务器实现文件和文件夹的上传与下载,python清理ftp目录下的所有文件和非空文件夹

简介: Python操作FTP服务器实现文件和文件夹的上传与下载,python清理ftp目录下的所有文件和非空文件夹

第一章:连接 FTP 服务器并实现文件夹上传

① 连接 FTP 服务器

如果 FTP 不用用户名密码就直接可以访问,那就是用的默认用户名 Anonymous,密码为空。

# -*- coding: UTF8 -*-
# 2022-3-10
# 作者:小蓝枣
# python连接ftp服务器
from ftplib import FTP
def conn_ftp():
    '''
     作用:连接ftp服务器
     参数:无
     返回:ftp服务器连接的对象
    '''
    # FTP连接信息
    ftp_ip = "xx.xx.xx.xx"
    # 默认端口21
    ftp_port = 21
    # 如果未指定,使用默认用户名为Anonymous,密码为空
    ftp_user = "Anonymous"
    ftp_password = ""
    ftp = FTP()
    # 连接ftp
    ftp.connect(ftp_ip, ftp_port)
    # ftp登录
    ftp.login(ftp_user, ftp_password)
    # 查看欢迎信息
    print(ftp.getwelcome())
    return ftp
ftp = conn_ftp()

② 区分文件和文件夹名

从方法 ftp.dir() 返回结果可以看到包含 <DIR> 标识的为文件夹,我们根据这个特征来进行文件夹区分。

def diff_dir(ftp, path):
    '''
     作用:区分文件和文件夹
     参数1:ftp连接对象
     参数2:要展示的目录
     返回:无
    '''
    # 进入指定目录
    ftp.cwd(path)
    # 显示当前所在位置
    print("当前所在位置为:")
    print(ftp.pwd())
    # 展示目录内容
    print("\n显示目录内容:")
    dirs = []
    ftp.dir(".", dirs.append)
    for i in dirs:
        # 区分文件和文件夹
        if("<DIR>" in i):
            print("目录为:" + i.split(" ")[-1])
        else:
            print("文件为:" + i.split(" ")[-1])
path = "/CaseData/nc.vo.sdp.testcase.testcase.TestcaseHVO/"
diff_dir(ftp, path)

f0075898e81d432fadd3f6f3c05ea1e0.png

③ 文件夹名包含空格处理

split(" ")[-1] 方法有个缺陷,如果文件或文件夹名里包含空格,得到到的文件夹名就不对了,下面的方法可以有效的解决这个问题

def get_dir_name(s):
    '''
     作用:需要文件或文件夹名
     参数1:需要截取的字符串
     返回:文件或文件夹名
    '''
    dir_name = ""
    k = 0
    record = ""
    for i in s:
        if(record == " " and i != " "):
            k = k + 1;
        if(k >= 3):
            dir_name = dir_name + i;
        record = i
    print(dir_name)
    return dir_name
# 测试两条数据
get_dir_name("03-08-22  09:52AM       <DIR>          C2021.11_ZDHJC_004a")
get_dir_name("03-08-25  10:32AM                89098 hello .exe")

d102afdc90b148df9b00042d1e43fac8.png

④ 使用递归实现:清理指定目录下所有的文件和非空文件夹

为什么强调非空呢,因为如果文件夹非空是没法直接删除的,只有当文件夹里的所有内容都删掉,文件夹为空时才可以删除。

import os
def dir_clear(ftp, dir_name):
    '''
     作用: 目录清空处理
     参数1:ftp连接对象
     参数2:目录或文件名
     返回:无
    '''
    # 进入指定目录
    ftp.cwd(dir_name)
    dirs = []
    ftp.dir(".", dirs.append)
    for i in dirs:
        try:
            if("<DIR>" in i):
                new_dir_name = get_dir_name(i)
                # 非空目录还删不了,先删除目录里的文件
                dir_clear(ftp, new_dir_name)
                ftp.rmd(new_dir_name)
            elif("<DIR>" not in i):
                new_file_name = get_dir_name(i)
                ftp.delete(new_file_name)
        except Exception as e:
            print("删除失败脚本:" + get_dir_name(i))
            print("失败原因:" + e)
    # 退出当前目录
    ftp.cwd("..")
path = "/CaseData/nc.vo.sdp.testcase.testcase.TestcaseHVO/"
# 文件清空
dir_clear(ftp, path)

执行后可以看到所有的文件和文件夹都被清空了:

591a82bc971c41faa461103a087e22e7.png


⑤ 使用递归实现:本地文件上传FTP服务器里的文件夹


思路:

1、并判断是否是目录,如果是目录的话,本地根据目录结构进行递归,同时在 FTP 服务器的对应位置创建文件夹。

2、需要判断原来的目录下是否存在同名的文件或文件夹,是的话要进行删除,这里用 delete_dir() 方法来实现,非空文件夹不能直接删除,还要进行递归处理,用上面的 dir_clear() 方法来实现。

3、由于文件和文件夹可以同名,但是不是同一种类型,怕误删,这里根据同名并同种类型来判断,如果原来列表里的文件较多,判断同类型的方法需要列表遍历,再加上上传的文件较多就会反复遍历列表影响效率,所以加个 current_dir 字符串的变量,可以先检查是否有同名的,如果没有直接跳过,提升效率,有的话再进行二次遍历。


注意:由于是一个 ftp 连接对象,递归过程中进去某个目录下,递归结束要回到之前的目录。

import pathlib
def delete_dir(ftp, isdir, dir_name, current_dir):
    '''
     作用: 判断目录或文件是否存在,存在的话删除
     参数1:ftp连接对象
     参数2:是否为目录,是的话为目录,不是的话为文件
     参数3:目录或文件名
     参数4:当前目录下的列表文件名集
     返回:无
    '''
    # 先初步判断下,不然直接循环遍历量大的影响效率
    if(dir_name not in current_dir):
        return
    dirs = []
    ftp.dir(".", dirs.append)
    for i in dirs:
        if(isdir == True and "<DIR>" in i):
            if(dir_name == get_dir_name(i)):
                # 非空目录还删不了,先删除目录里的文件
                dir_clear(ftp, dir_name)
                ftp.rmd(dir_name)
        elif(isdir == False and "<DIR>" not in i):
            if(dir_name == get_dir_name(i)):
                ftp.delete(dir_name)
def upload_dir(ftp, path, local_path):
    '''
     作用: 上传目录
     参数1:ftp连接对象
     参数2:远程路径
     参数3:本地存放路径
     返回:无
    '''
    print(path)
    # 进入指定目录
    ftp.cwd(path)
    # 获取当前目录的一个列表
    current_dir = ""
    for i in ftp.nlst():
        current_dir = current_dir + " " + i
    # 遍历本地路径
    for i in os.listdir(local_path):
        new_local_path = local_path + '/' + i
        # 判断为文件
        if(os.path.isfile(new_local_path)):
            # 如果有同名文件,删除
            delete_dir(ftp, False, i, current_dir)
            f = open(new_local_path, 'rb')
            # 上传文件
            ftp.storbinary("STOR " + i, f)
            f.close()
        # 判断为文件夹
        elif(os.path.isdir(new_local_path)):
            # 如果有同名文件夹,删除
            delete_dir(ftp, True, i, current_dir)
            # 创建目录
            print(i)
            try:
                ftp.mkd(i)
                upload_dir(ftp, i, new_local_path);
            except Exception as e:
                print("文件夹上传失败:" + get_dir_name(i))
                print("失败原因:" + e)
    # 退出当前目录
    ftp.cwd("..")
# 设置编码,解决上传的文件包含中文的问题
ftp.encoding = 'GBK'
path = "/CaseData/nc.vo.sdp.testcase.testcase.TestcaseHVO/"
local_path = "D:/ftp上传"
upload_dir(ftp, path, local_path)

这是本地的路径。


510c596cdd5944a3bcb19b9e0530cc85.png

这里服务器路径,可以看到里面的嵌套目录也同步被上传了。


b9984bffd2624f519b718d2087116a56.png


第二章:相关问题

① 上传的文件名包含中文【‘utf-8’ codec can’t decode byte …】

设置下 FTP 对象的编码为 GBK 即可。

ftp.encoding = 'GBK'

不然会报如下错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 114: invalid continuation byte

② 指定的路径存在问题【550 The system cannot find the file specified.】

开始我用 split(" ")[-1] 方法截取文件名,由于有的文件含有中文,截取后的文件名称不对了。

就报了 ftplib.error_perm: 550 The system cannot find the file specified. 的错误。

③ 上传文件前未加STOR标识【500 Command not understood.】

上传文件时 FTP 路径前要加个 'STOR ',不然就会报 500 错误,注意后面还跟了个空格。

# 上传文件
ftp.storbinary("STOR " + i, f)


不然就报 ftplib.error_perm: 500 Command not understood. 错误了。

④ 上传文件夹包含中文名【暂未解决】


目前 ftp.mkd(i) 方法创建文件夹时如果包含中文名时会报错,暂未找到解决方法。

喜欢的点个赞❤吧!


目录
相关文章
|
8月前
|
人工智能 JavaScript API
零基础构建MCP服务器:TypeScript/Python双语言实战指南
作为一名深耕技术领域多年的博主摘星,我深刻感受到了MCP(Model Context Protocol)协议在AI生态系统中的革命性意义。MCP作为Anthropic推出的开放标准,正在重新定义AI应用与外部系统的交互方式,它不仅解决了传统API集成的复杂性问题,更为开发者提供了一个统一、安全、高效的连接框架。在过去几个月的实践中,我发现许多开发者对MCP的概念理解透彻,但在实际动手构建MCP服务器时却遇到了各种技术壁垒。从环境配置的细节问题到SDK API的深度理解,从第一个Hello World程序的调试到生产环境的部署优化,每一个环节都可能成为初学者的绊脚石。因此,我决定撰写这篇全面的实
1869 67
零基础构建MCP服务器:TypeScript/Python双语言实战指南
|
7月前
|
人工智能 自然语言处理 安全
Python构建MCP服务器:从工具封装到AI集成的全流程实践
MCP协议为AI提供标准化工具调用接口,助力模型高效操作现实世界。
1283 1
|
10月前
|
人工智能 安全 Shell
Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程
Jupyter MCP服务器基于模型上下文协议(MCP),实现大型语言模型与Jupyter环境的无缝集成。它通过标准化接口,让AI模型安全访问和操作Jupyter核心组件,如内核、文件系统和终端。本文深入解析其技术架构、功能特性及部署方法。MCP服务器解决了传统AI模型缺乏实时上下文感知的问题,支持代码执行、变量状态获取、文件管理等功能,提升编程效率。同时,严格的权限控制确保了安全性。作为智能化交互工具,Jupyter MCP为动态计算环境与AI模型之间搭建了高效桥梁。
667 2
Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程
|
8月前
|
安全 Linux 网络安全
Python极速搭建局域网文件共享服务器:一行命令实现HTTPS安全传输
本文介绍如何利用Python的http.server模块,通过一行命令快速搭建支持HTTPS的安全文件下载服务器,无需第三方工具,3分钟部署,保障局域网文件共享的隐私与安全。
1952 0
|
弹性计算 网络协议 Linux
|
5月前
|
弹性计算 运维 安全
阿里云轻量应用服务器与云服务器ECS啥区别?新手帮助教程
阿里云轻量应用服务器适合个人开发者搭建博客、测试环境等低流量场景,操作简单、成本低;ECS适用于企业级高负载业务,功能强大、灵活可扩展。二者在性能、网络、镜像及运维管理上差异显著,用户应根据实际需求选择。
439 10
|
5月前
|
运维 安全 Ubuntu
阿里云渠道商:服务器操作系统怎么选?
阿里云提供丰富操作系统镜像,涵盖Windows与主流Linux发行版。选型需综合技术兼容性、运维成本、安全稳定等因素。推荐Alibaba Cloud Linux、Ubuntu等用于Web与容器场景,Windows Server支撑.NET应用。建议优先选用LTS版本并进行测试验证,通过标准化镜像管理提升部署效率与一致性。
|
5月前
|
弹性计算 ice
阿里云4核8g服务器多少钱一年?1个月和1小时价格,省钱购买方法分享
阿里云4核8G服务器价格因实例类型而异,经济型e实例约159元/月,计算型c9i约371元/月,按小时计费最低0.45元。实际购买享折扣,1年最高可省至1578元,附主流ECS实例及CPU型号参考。
599 8
|
5月前
|
存储 监控 安全
阿里云渠道商:云服务器价格有什么变动?
阿里云带宽与存储费用呈基础资源降价、增值服务差异化趋势。企业应结合业务特点,通过阶梯计价、智能分层、弹性带宽等策略优化成本,借助云监控与预算预警机制,实现高效、可控的云资源管理。

推荐镜像

更多