• 目录结构:
FTP_project/
├── FTP_client
│   ├── ftp_client.py
│   └── __init__.py
└── FTP_server
├── bin
│   ├── ftp_server.py
│   └── __init__.py
├── conf
│   ├── accounts.cfg
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── settings.cpython-36.pyc
│   └── settings.py
├── core
│   ├── __init__.py
│   ├── main.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── main.cpython-36.pyc
│   │   └── server.cpython-36.pyc
│   └── server.py
├── home
│   ├── __init__.py
│   ├── monitor
│   │   └── __init__.py
│   └── root
└── logger
└── __init__.py

  

  • 代码相关

     import optparse, socket
    import configparser
    import json
    import os, sys STATUS_CODE = {
    250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
    251 : "Invalid cmd ",
    252 : "Invalid auth data",
    253 : "Wrong username or password",
    254 : "Passed authentication", 800 : "the file exist,but not enough ,is continue? ",
    801 : "the file exist !",
    802 : " ready to receive datas", 900 : "md5 valdate success" } class ClientHandler(): def __init__(self):
    # 解析python FTP_client 后面接的参数
    self.op = optparse.OptionParser() self.op.add_option('-s','--server',dest='server')
    self.op.add_option('-P','--port',dest='port')
    self.op.add_option('-u','--username',dest='username')
    self.op.add_option('-p','--password',dest='password')
    # options(定义的参数),args(未定义的参数)
    self.options, self.args = self.op.parse_args()
    self.verify_args(self.options, self.args)
    self.make_connecton()
    self.mainPath = os.path.dirname(os.path.abspath(__file__))
    self.last = 0 def verify_args(self, options, args):
    server = options.server
    port = options.port
    username = options.username
    password = options.password
    if int(port) > 0 and int(port) < 65535:
    return True
    else:
    exit('The port is in 0-65535') def make_connecton(self):
    self.sock = socket.socket()
    self.sock.connect((self.options.server, int(self.options.port))) def interaction(self): #登陆函数
    print('begin to interaction....')
    #验证登陆信息
    if self.authenticate():
    while 1:
    cmd_info = input('[%s]' %self.current_dir).strip() # put 12.png images cmd_list = cmd_info.split()
    if hasattr(self, cmd_list[0]):
    func = getattr(self, cmd_list[0])
    func(*cmd_list)
    else:
    print('Commond is not found!') def authenticate(self): # 账号密码输入
    if self.options.username is None or self.options.password is None:
    username = input('username: ')
    password = input('password: ')
    return self.get_auth_result(username,password)
    return self.get_auth_result(self.options.username, self.options.password) def response(self):
    data = self.sock.recv(1024).decode('utf8')
    data = json.loads(data)
    return data def get_auth_result(self, user, pwd):
    data = {
    'action':'auth',
    'username':user,
    'password':pwd
    } self.sock.send(json.dumps(data).encode('utf8'))
    response = self.response()
    print('response:' ,response['status_code'])
    if response['status_code'] == 254:
    self.user = user
    self.current_dir = user
    print(STATUS_CODE[254])
    return True
    else:
    print(STATUS_CODE[response['status_code']]) def put(self, *cmd_list):
    # put file_name 路径
    action, local_path, target_path=cmd_list
    local_path = os.path.join(self.mainPath, local_path ) file_name = os.path.basename(local_path)
    file_size = os.stat(local_path).st_size data = {
    'action':'put',
    'file_name':file_name,
    'file_size':file_size,
    'target_path':target_path
    } self.sock.send(json.dumps(data).encode('utf8'))
    is_exist = self.sock.recv(1024).decode('utf8')
    ##########################
    has_sent = 0
    if is_exist == '':
    # 文件不完整
    choice = input('The file exist,but not enouth,is continue? [Y/N]').strip()
    if choice.upper() == 'Y':
    self.sock.sendall('Y'.encode('utf8'))
    continue_position = self.sock.recv(1024).decode('utf8')
    has_sent += int(continue_position)
    else:
    self.sock.sendall('N'.encode('utf8')) elif is_exist == '':
    # 文件完全存在
    print('The file exist!')
    return
    else:
    pass f = open(local_path, 'rb')
    while has_sent < file_size:
    data = f.read(1024)
    self.sock.sendall(data)
    has_sent += len(data)
    self.show_progress(has_sent, file_size)
    f.close()
    print('put success') def show_progress(self, has, total):
    rate = float(has)/float(total)
    rate_num = int(rate * 100)
    if self.last != rate_num:
    sys.stdout.write('%s%% %s\r' %(rate_num,'#'*rate_num))
    self.last = rate_num def ls(self, *cmd_list):
    data = {'action':'ls'}
    self.sock.sendall(json.dumps(data).encode('utf8'))
    data = self.sock.recv(1024).decode('utf8')
    print(data) def cd(self, *cmd_list):
    # cd images
    data = {
    'action':'cd',
    'dirname':cmd_list[1]
    }
    self.sock.send(json.dumps(data).encode('utf8'))
    data = self.sock.recv(1024).decode('utf8')
    if data != 'Directory is not exist!':
    self.current_dir = os.path.basename(data)
    else:
    print(data) def mkdir(self, *cmd_list):
    data = {
    'action':'mkdir',
    'dirname':cmd_list[1]
    } self.sock.sendall(json.dumps(data).encode('utf8'))
    ret = self.sock.recv(1024).decode('utf8')
    print(ret) def rm(self, *cmd_list):
    data = {
    'action':'rm',
    'file_name':cmd_list[1]
    }
    self.sock.send(json.dumps(data).encode('utf8'))
    data = self.sock.recv(1024).decode('utf8')
    print(data) def pwd(self, *cmd_list):
    data = {'action':'pwd'}
    self.sock.sendall(json.dumps(data).encode('utf8'))
    data = self.sock.recv(1024).decode('utf8')
    print(data) def quit(self, *cmd_list):
    data = {'action':'quit'} ch = ClientHandler() ch.interaction()

    ftp_client.py

     # coding=gbk
    
     import os, sys
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(PATH) from core import main if __name__ == '__main__':
    main.ArgvHandler()

    ftp_server.py

     [DEFAULT]
    
     [monitory]
    Password = 123
    Quotation = 100 [root]
    Password = root
    Quotation = 100

    accounts.cfg

     import os , sys
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) IP="127.0.0.1"
    PORT = 8080 ACCOUNT_PATH = os.path.join(BASE_DIR,"conf",'accounts.cfg')

    settings.py

     import os, sys
    import optparse, socketserver
    # PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    # sys.path.append(PATH)
    from conf import settings
    from core import server class ArgvHandler():
    def __init__(self):
    self.op = optparse.OptionParser()
    # self.op.add_option('-s','--s',dest = 'server')
    # self.op.add_option('-P','--port',dest = 'port')
    options, args = self.op.parse_args() # python ftp_server.py -s 127.0.0.1 -P 8080 123
    # options:add_option配置过的参数,args:add_option中没有定义的参数
    # print(options.server)
    # print(options.port)
    # print(args) self.verify_args(options, args) def verify_args(self, options, args):
    if args:
    cmd = args[0]
    if hasattr(self, cmd):
    func = getattr(self, cmd)
    func()
    else:
    print('There is no such parameter')
    else:
    print('Usage [start]') def start(self):
    print('server is working')
    s = socketserver.ThreadingTCPServer((settings.IP,settings.PORT), server.ServerHandler)
    s.serve_forever() def help(self):
    pass

    main.py

     import socketserver, configparser
    import json
    from conf import settings
    import os, sys STATUS_CODE = {
    250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
    251 : "Invalid cmd ",
    252 : "Invalid auth data",
    253 : "Wrong username or password",
    254 : "Passed authentication", 800 : "the file exist,but not enough ,is continue? ",
    801 : "the file exist !",
    802 : " ready to receive datas", 900 : "md5 valdate success" } class ServerHandler(socketserver.BaseRequestHandler): def handle(self):
    while True:
    #conn = self.request data=self.request.recv(1024).strip()
    if len(data)==0:break data=json.loads(data.decode("utf8"))
    print("data:",data)
    '''
    {'action':'auth',
    'username':'xxxx',
    'pwd':123
    }
    '''
    if data.get('action'):
    if hasattr(self, data.get('action')):
    func = getattr(self, data.get('action'))
    func(**data)
    else:
    print('Invalid cmd')
    else:
    print('Invalid cmd2') def send_reponse(self, status_code):
    response = {'status_code':status_code}
    self.request.sendall(json.dumps(response).encode('utf8')) def auth(self, **data):
    username = data['username']
    password = data['password']
    user = self.authenticate(username, password) if user:
    self.send_reponse(254)
    else:
    self.send_reponse(253) def authenticate(self, user, pwd):
    cfg = configparser.ConfigParser()
    cfg.read(settings.ACCOUNT_PATH) if user in cfg.sections():
    if cfg[user]['Password'] == pwd:
    self.user=user
    self.mainPath = os.path.join(settings.BASE_DIR, 'home', self.user)
    print('passwd authentication')
    return user def put(self, **data):
    print('data')
    file_name = data.get('file_name')
    file_size = data.get('file_size')
    target_path = data.get('target_path') abs_path = os.path.join(self.mainPath, target_path, file_name) #######################################传输
    has_received = 0
    if os.path.exists(abs_path):
    file_has_size = os.stat(abs_path).st_size
    if file_has_size < file_size:
    # 断点续传
    self.request.sendall(''.encode('utf8'))
    choice = self.request.recv(1024).decode('utf8')
    if choice == 'Y':
    self.request.sendall(str(file_has_size).encode('utf8'))
    has_received = file_has_size
    f = open(abs_path, 'ab')
    else:
    f = open(abs_path, 'wb')
    else:
    # 文件完全存在
    self.request.sendall(''.encode('utf8'))
    return else:
    self.request.sendall(''.encode('utf8'))
    f = open(abs_path, 'wb') while has_received < file_size:
    try:
    data = self.request.recv(1024)
    except Exception as e:
    break
    f.write(data)
    has_received += len(data)
    f.close() def ls(self,**data):
    file_list = os.listdir(self.mainPath) # 加入当前目录下的文件到列表
    file_str='\n'.join(file_list)
    if not len(file_str):
    file_str='<empty dir> '
    self.request.sendall(file_str.encode('utf8')) def cd(self, **data):
    dirname = data.get('dirname') if dirname == '..':
    self.mainPath = os.path.dirname(self.mainPath)
    self.request.sendall(self.mainPath.encode('utf8'))
    elif os.path.exists(os.path.join(self.mainPath, dirname)):
    self.mainPath = os.path.join(self.mainPath, dirname)
    self.request.sendall(self.mainPath.encode('utf8'))
    else:
    self.request.sendall('Directory is not exist!'.encode('utf8')) def mkdir(self, **data):
    dirname = data.get('dirname')
    # 新目录名
    path = os.path.join(self.mainPath, dirname)
    # 判断目录名是否存在
    if not os.path.exists(path):
    if '/' in dirname:
    os.makedirs(path)
    else:
    os.mkdir(path)
    self.request.sendall('create success'.encode('utf8'))
    else:
    self.request.sendall('dirname is exist'.encode('utf8')) def rm(self, **data):
    filename = data.get('file_name')
    filename1 = os.path.join(self.mainPath, filename)
    os.remove(filename1)
    self.request.sendall('file is removed!'.encode('utf8')) def pwd(self, **data):
    self.request.sendall(self.mainPath.encode('utf8'))

    server.py

Python3 实现FTP功能的更多相关文章

  1. libcurl编译使用,实现ftp功能

    Libcurl实现ftp的下载,上传功能.版本为curl-7.63.0 1.编译vs2015 参考资料:https://blog.csdn.net/yaojingkao/article/details ...

  2. 使用commons-net做FTP功能的异常 java.lang.ClassNotFoundException: org.apache.oro.text.regex.Malformed

    最近使用Apache的commons-net.jar做FTP上传下载功能,点击“上传”的时候报错,如下: java.lang.ClassNotFoundException: org.apache.or ...

  3. python网络编程--socketserver 和 ftp功能简单说明

    1. socketserver 我们之前写的tcp协议的socket是不是一次只能和一个客户端通信,如果用socketserver可以实现和多个客户端通信.它是在socket的基础上进行了一层封装,也 ...

  4. Win7的ftp功能

    ftp作为文件传输协议,在一些特殊情况下用这种文件传输是比较方便的,并且win7本身也支持这个功能,在控制面板--->程序-->打开或关闭Windows功能,安装即可: 然后在管理控制台中 ...

  5. python socketserver 实现 ftp功能

    需求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当前目 ...

  6. python 基于windows环境的ftp功能

    描述: 1.基于备份服务器部署的py程序,将需要备份主机目录下的内容下载至备份服务器(服务端和远端都是windows server 2008) 2.py程序部署在windows服务器,后台运行,基于b ...

  7. centos启用ftp功能

    1.安装vsftpd组件,安装完后,有/etc/vsftpd/vsftpd.conf 文件,用来配置,还有新建了一个ftp用户和ftp的组,指向home目录为/var/ftp,默认是nologin(不 ...

  8. 给ubuntu开通FTP功能

    一.安装vsftp安装: sudo apt-get install vsftpd 二.启动.停止.重启vsftp 启动vsftp:sudo service vsftpd start 三.创建ftp用户 ...

  9. day29 socketsever ftp功能简单讲解

    今日所学 一.ftp上传简单实例 二.socketsever的固定用法 三.验证合法性连接 1.ftp上传实例 这个题目是我们现在网络编程比较基础一点的题目 下面我们只写简单上传的代码 上传服务端的代 ...

随机推荐

  1. laradock 部署 php 环境 和 laravel/lumen 框架

    环境是windows 10 版本1809,docker 版本18.09.0 首先是下载docker.git, 具体可以参考 http://laradock.io/ 要求 Docker >= 17 ...

  2. 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题2---CMAKE配置问题

    实际上这里说的是移植的第一步,下载到源码后,我用的是opencv2.4.9,解压缩,然后可以利用cmake-gui来进行configure配置,这里面需要设置交叉编译的工具链,具体的可以参考[Linu ...

  3. 【Linux开发】arm-linux-gnueabihf-gcc下载

    原文地址:http://www.veryarm.com/arm-linux-gnueabihf-gcc veryarm是个不错的网站,里面介绍了很多相关的基础知识. arm-linux-gnueabi ...

  4. vue防止 由于网速出现 闪现{{}}

    防止闪现可能应为网速的原因{{msg}} 一直解析不了, 于是用户就看到它了,不友好, 于是 vue推出 与css配合 [v-cloak] {display:none}

  5. C++中的新型类型转换

    1,C 语言中已经有类型之间的强制转换,C++ 做了改善: 2,C 方式的强制类型转换: 1,(Type) (Expression): 2,Type (Expression): 1,这种方式和上述方式 ...

  6. 17: VUE数据绑定 与 Object.defineProperty

    VUE数据绑定原理:https://segmentfault.com/a/1190000006599500?utm_source=tag-newest Object.defineProperty(): ...

  7. es6中let实例应用之一

    有如下情景 html部分: <button class="btn">按钮1</button> <button class="btn" ...

  8. css水平垂直居中问题

    水平居中: 行内元素:text-align:center; 块级元素:magin:0 auto; 子元素设置:position:absolute;  left:50%;  transform:tran ...

  9. git init error:Malformed value for push.default: simple

    git init error:Malformed value for push.default: simple 1.git config --global push.default matching

  10. Python 通过wmi获取Window服务器硬件信息

    通过pip install wmi安装wmi 查看cpu序列号: wmic cpu get processorid 查看主板序列号: wmic baseboard get serialnumber 查 ...