python之Pyftpdlib第三方库在本机搭建FTP服务器

前言

1、在同一个局域网的多台电脑,传递文件时可以通过搭建web服务器,设置目录浏览的方式快速分享。如果上传就比较麻烦了,通过QQ/微信会产生很多文件记录,通过teamviewer太慢,其实FTP服务器倒是一个不错的选择。

2、FTP服务器软件在日常开发中,基本不会用到。还涉及 macOS、 Windows的环境差异,非常麻烦。虽然有免费开源的 filezzila,配置还是很繁琐的。

3、Python语言 + pyftpdlib 库实现局域网文件互传:一般来说,开发机都会安装Python环境,再安装 pyftpdlib 库就可以搭建在本地计算机搭建一个FTP服务。从而实现局域网内的文件互传。

4、通常Linux主机都是使用vsftp,pureftp来搭建FTP服务器,但配置很复杂。如果在工作中或者项目上只是临时使用FTP服务器,可以用python的 pyftpdlib 库。

下载与安装

pip install pyftpdlib

FTP服务器环境搭建

1、一行代码实现FTP服务器:

通过Python的 -m 选项作为一个简单的独立服务器来运行,当你想快速共享一个目录的时候,这是特别有用的。

在需要共享的目录下打开终端执行如下命令即可把当前目录共享出去(匿名登录)

python -m pyftpdlib

运行结果:

至此,一个简单的FTP服务器已经搭建完成,访问 ftp://127.0.0.1:2121 即可,如下:(默认FTP的IP为 127.0.0.1 、端口为 2121 )

2、命令行可选参数:

  •  -i : 指定IP地址(默认为本机的IP地址)

  • -p : 指定端口(默认为2121)

  • -w :写权限(默认为只读)

  • -d : 指定目录 (默认为当前目录)

  • -u :指定用户名登录

  • -P:设置登录密码

带参数命令行方式运行FTP服务器:

python -m pyftpdlib -w -d [PATH] -u [USER] -P [PASSWORD]

例如:

python -m pyftpdlib -w -d ~/Desktop -u admin -P 123456

实例:

如果觉得每次终端输入命令比较繁琐,可以创建脚本:设置根目录为桌面、帐号为admin、密码为123456;保存为名为StartFTP的文件。在使用时点击打开,使用后点击关闭即可。

(1)macOS 操作系统或 Linux 操作系统下,保存为StartFTP文件, 并 chmod 755 ./StartFTP 将该文件设置为执行文件,可执行文件内容如下:

#/bin/bash
python -m pyftpdlib -w -d ~/Desktop -u admin -P 123456

(2)Windows操作系统下保存为bat文件,bat文件内容如下:

@echo off
echo FTP Starting...
python -m pyftpdlib -w -d %HOMEDRIVE%%HOMEPATH%\Desktop -u admin -P 123456

搭建一个功能强大完善的FTP服务

1、上述的一行命令已经可以实现一个简单的FTP服务器,但是要搭建一个功能强大完善的FTP服务所涉及到的配置较多,这时需要使用 Pyftpdlib 库提供的 API 来编写。

2、名词解释:

 pyftpdlib.ftpservers.FTPServer  : 接收客户端连接,然后分发给对应的程序。

 pyftpdlib.handlers.FTPHandler  : 一个表示服务器协议解释器的类,每次出现一个新的连接FTPServer将创建一个新的FTPHandler实例来处理当前PI会话。

 pyftpdlib.handlers.ActiveDIP 和 pyftpdlib.handlers.PassiveDIP  : 主动模式和被动模式的基础类。

 pyftpdlib.handlers.DTPHandler  : 这个类处理的是数据传输进程。

 pyftpdlib.authorizers.DummyAuthorizer  : 处理FTP的认证和权限的处理类,用于处理用户密码,获取用户的家目录和权限,DummyAuthorizer 是基础的认证模块的类,提供平台无关接口的基础授权程序类
用于管理虚拟用户。

 pyftpdlib.filesystems.AbstractedFS  : 类用于与文件系统交互,提供了一个高级的,跨平台接口兼容Windows和UNIX风格文件系统。

3、实例如下:

#!/usr/bin/env python3
# coding:utf-8

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import os

global author


def ftp_server(username, password, directory):
    """
    启动一个ftp的server进程

    :param username: 需要添加用户的用户名
    :param password: 用户的密码
    :param directory: 用户的家目录,也就是FTP服务器的数据目录
    :return:
    """

    # 如果目录不存在,就创建目录

    global author
    if not os.path.exists(directory):
        os.mkdir(directory)

    try:
        # 实例化DummyAuthorizer来创建ftp用户
        author = DummyAuthorizer()
        # 参数:用户名,密码,目录,权限
        author.add_user(username, password, directory, perm="elradfmw")

        # 匿名登录
        # authorizer.add_anonymous(directory)
    except OSError as e:
        if "Address already in use" in e:
            print("21号端口被占用")

    # 初始化ftp句柄
    handler = FTPHandler
    handler.authorizer = author

    # 添加被动端口范围
    handler.passive_ports = range(2000, 2400)

    # 启动server,本地执行,监听21号端口(参数:IP,端口,handler)
    server = FTPServer(('0.0.0.0', 21), handler)
    server.serve_forever()


if __name__ == '__main__':
    ftp_server(username="zhanghao", password="aixocm", directory="/data/zhanghao")

正常执行脚本启动FTP服务:

[root@zhanghao python-learning]# python3 ftptest.py 
[I 2021-01-09 05:40:02] concurrency model: async
[I 2021-01-09 05:40:02] masquerade (NAT) address: None
[I 2021-01-09 05:40:02] passive ports: 2000->2399
[I 2021-01-09 05:40:02] >>> starting FTP server on 0.0.0.0:32, pid=4772 <<<

客户端连接:

[root@zhserver zhanghao]# ftp 192.168.0.101
Connected to 192.168.0.101 (192.168.0.101).
220 pyftpdlib 1.5.6 ready.
Name (192.168.0.101:root): zhanghao
331 Username ok, send password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.

4、FTP服务器资源限制:

from pyftpdlib.handlers import ThrottledDTPHandler

transport_handler = ThrottledDTPHandler
transport_handler.read_limit = 200 * 1024
transport_handler.write_limit = 100 * 1024
handler.dtp_handler = transport_handler

5、添加输出log:

脚本中添加日志,输出到屏幕以及日志文件,日志文件名称为ftp.log。

from pyftpdlib.log import LogFormatter
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

stream = logging.StreamHandler()
log_file = logging.FileHandler(filename="ftp.log", encoding="utf-8")

stream.setFormatter(LogFormatter())
log_file.setFormatter(LogFormatter())

logger.addHandler(stream)
logger.addHandler(log_file)

6、用户权限:

读取权限:

  • "e" :更改目录(CWD,CDUP命令)

  • "l" :列表文件(LIST,NLST,STAT,MLSD,MLST,SIZE命令)

  • "r" :从服务器检索文件(RETR命令)

写入权限:

  • "a" :将数据追加到现有文件(APPE命令)

  • "d" :删除文件或目录(DELE,RMD命令)

  • "f" :重命名文件或目录(RNFR,RNTO命令)

  • "m" :创建目录(MKD命令)

  • "w" :将文件存储到服务器(STOR,STOU命令)

  • "M":更改文件模式/权限(SITE CHMOD命令)

  • "T":更改文件修改时间(SITE MFMT命令)

总结:

ftplib客户端实现

from ftplib import FTP


def ftp_client(host_ip, username, password):
    """
    ftp客户端程序
    :param host_ip:ftp server的IP地址
    :param username: 连接server端的用户名
    :param password: 用户密码
    :return:
    """
    ftp_client = FTP(host=host_ip, user=username, passwd=password)
    ftp_client.encoding = 'gbk'

    # 执行客户端的操作
    ftp_client.cwd()

简单示例

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

# 实例化DummyAuthorizer来创建ftp用户
authorizer = DummyAuthorizer()
# 参数:用户名,密码,目录,权限
authorizer.add_user('user', '12345', '/opt/pyftp/test', perm='elradfmwMT')
# 匿名登录
# authorizer.add_anonymous('/home/nobody')
handler = FTPHandler
handler.authorizer = authorizer
# 参数:IP,端口,handler
server = FTPServer(('192.168.56.100', 21), handler)
server.serve_forever()

 

posted @ 2022-07-27 09:25  习久性成  阅读(2423)  评论(0编辑  收藏  举报