zoukankan      html  css  js  c++  java
  • python基础之FTP

    目的:实现客户端到服务器的上传功能

    所需文件夹:

    客户端是FTP_client             服务端是FTP_server

    bin文件存放执行文件,conf下存放配置文件,core下是核心文件,home是家目录,logger存放日志文件.

    客户端代码    ftp_client.py:

    import optparse
    import socket
    import os,sys
    import json
    import time
    import hashlib
    
    STATUS_CODE = {
        250: "Invalid cmd format,e.g:{'action':'get','filname':'test.py','size':344}",
        251: "Incalid cmd",
        252: "Invalid auth data",
        253: "Wrong username or password",
        254: "Passed authentication",
        255: "Filename doesn't provided",
        256: "Filename doesn't exist on the server",
        257: "Ready to send file",
        258: "md5 verification",
    
        800: "The file exist,but not enough,is continue?",
        801: "The file exist!",
        802: "Ready to receive datas",
    
        900: "md5 validate success"
    }
    
    class ClientHandler():
        def __init__(self):
            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")
    
            self.options,self.args = self.op.parse_args()
            self.verify_args(self.options,self.args)
            self.make_connection()
            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_connection(self):
            self.sock = socket.socket()
            self.sock.connect((self.options.server,int(self.options.port)))
    
        def interactive(self):
            print("Begin to interactive...")
            if self.authenticate():
                while True:
                    cmd_info = input("[%s]"%self.current_dir).strip()
                    cmd_list = cmd_info.split()
                    if hasattr(self,cmd_list[0]):
                        func = getattr(self,cmd_list[0])
                        func(*cmd_list)
    
        def put(self,*cmd_list):
            # put 12.jpg images
            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('utf-8'))
    
            is_exist = self.sock.recv(1024).decode('utf-8')
            ######################
            has_sent = 0
            if is_exist=="800":
                #文件完整
                choice = input("The file exist,but not enough,is continue?[Y/N]").strip()
                if choice.upper()=='Y':
                    self.sock.sendall("Y".encode('utf-8'))
                    continue_position = self.sock.recv(1024).decode('utf-8')
                    has_sent+=int(continue_position)
    
    
                else:
                    self.sock.sendall("N".encode('utf-8'))
    
            elif is_exist=="801":
                #文件完全存在
                print('The file exist')
                return
    
            f = open(local_path,"rb")
            f.seek(has_sent)
            start = time.time()
            md5_obj = hashlib.md5()
            while has_sent<file_size:
                data = f.read(1024)
                self.sock.sendall(data)
                has_sent+=len(data)
                md5_obj.update(data)
                self.show_process(has_sent,file_size)
            else:
                print("post success!!!")
                md5_val = md5_obj.hexdigest()
                md5_server = self.sock.recv(1024).decode('utf-8')
                print(md5_server)
                self.sock.sendall(md5_val.encode('utf-8'))
    
            f.close()
            print("Put Success")
    
        def show_process(self,has,total):
            rate = float(has)/float(total)
            rate_num = int(rate*100)
            rate_num_1 = int(rate_num/2)
            if self.last!=rate_num:
                sys.stdout.write("%s%% %s
    "%(rate_num,"#"*rate_num_1))
            self.last = rate_num
    
        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('utf-8')
            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('utf-8'))
            response = self.response()
            print(response)
            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 ls(self,*cmd_list):
            data = {
                "action":"ls",
            }
            self.sock.sendall(json.dumps(data).encode('utf-8'))
            data = self.sock.recv(1024).decode('utf-8')
            print(data)
    
        def cd(self,*cmd_list):
            data = {
                "action": "cd",
                "dirname": cmd_list[1],
            }
            self.sock.send(json.dumps(data).encode('utf-8'))
    
            data = self.sock.recv(1024).decode('utf-8')
            self.current_dir = self.user + "\" +os.path.basename(data)
    
    
    
    ch = ClientHandler()
    ch.interactive()
    View Code

    服务端代码      启动代码ftp_server.py

    import os,sys
    BaseAddress = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(BaseAddress)
    from core import main
    if __name__ == '__main__':
        main.ArgvHandler()
    View Code

    核心代码     main.py

    import optparse
    import socketserver
    from conf import settings
    from core import server
    
    class ArgvHandler():
        def __init__(self):
            self.op = optparse.OptionParser()
            # self.op.add_option('-s','--server',dest='server')
            # self.op.add_option('-P','--port',dest='port')
            # self.op.add_option('-s','--s',dest='server')
    
            options,args = self.op.parse_args()
            self.verify_args(options,args)
    
        def verify_args(self,options,args):
            cmd = args[0]
            if hasattr(self,cmd):
                func = getattr(self,cmd)
                func()
    
        def start(self):
            print('the server is working...')
            s = socketserver.ThreadingTCPServer((settings.IP,settings.PORT),server.SeverHandler)
            s.serve_forever()
    
        def help(self):
            pass
    View Code

    执行代码

    import socketserver
    import json
    import configparser
    from conf import settings
    import os
    import hashlib
    
    STATUS_CODE = {
        250: "Invalid cmd format,e.g:{'action':'get','filname':'test.py','size':344}",
        251: "Incalid cmd",
        252: "Invalid auth data",
        253: "Wrong username or password",
        254: "Passed authentication",
        255: "Filename doesn't provided",
        256: "Filename doesn't exist on the server",
        257: "Ready to send file",
        258: "md5 verification",
    
        800: "The file exist,but not enough,is continue?",
        801: "The file exist!",
        802: "Ready to receive datas",
    
        900: "md5 validate success"
    }
    
    class SeverHandler(socketserver.BaseRequestHandler):
        def handle(self):
            while 1:
                data = self.request.recv(1024).strip()
                data = json.loads(data.decode('utf-8'))
    
                if data.get("action"):
                    if hasattr(self,data.get("action")):
                        func = getattr(self,data.get("action"))
                        func(**data)
                else:
                    print('Invalid cmd')
    
        def send_response(self,state_code):
            response = {"status_code":state_code,'status_mes':STATUS_CODE[state_code]}
            self.request.sendall(json.dumps(response).encode('utf-8'))
    
        def auth(self,**data):
            username = data['username']
            password = data['password']
    
            user = self.authenticate(username,password)
    
            if user:
                self.send_response(254)
            else:
                self.send_response(253)
    
        def authenticate(self,user,pwd):
            config = configparser.ConfigParser()
            config.read(settings.ACCOUNT_PATH)
    
    
            if user in config.sections():
                print("================================")
    
                if config[user]["Password"]==pwd:
                    self.user = user
                    self.mainPath = os.path.join(settings.BASE_DIR,"home",self.user)
    
                    print("passed authentication")
                    return self.user
    
        def put(self,**data):
            print("data: ",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("800".encode('utf-8'))
                    choice = self.request.recv(1024).decode('utf-8')
                    if choice=="Y":
                        self.request.sendall(str(file_has_size).encode('utf-8'))
                        has_received+=file_has_size
                        f = open(abs_path,"ab")
                    else:
                        f = open(abs_path,'wb')
    
                else:
                    #文件完全存在
                    self.request.sendall("801".encode('utf-8'))
                    return
    
            else:
                self.request.sendall("802".encode('utf-8'))
                f = open(abs_path,"wb")
    
            md5_obj = hashlib.md5()
            while has_received<file_size:
                try:
                    data = self.request.recv(1024)
                    md5_obj.update(data)
                except Exception as e:
                    break
                f.write(data)
                has_received+=len(data)
            md5_val = md5_obj.hexdigest()
            self.request.sendall(md5_val.encode('utf-8'))
            md5_client = self.request.recv(1024)
            print(md5_client)
            f.close()
    
        def ls(self,**data):
            file_list = os.listdir(self.mainPath)
            file_str = "
    ".join(file_list)
            if not len(file_list):
                file_str="<empty>"
            self.request.sendall(file_str.encode('utf-8'))
    
        def cd(self,**data):
            dirname = data.get("dirname")
            if dirname=="..":
                self.mainPath = os.path.dirname(self.mainPath)
            else:
                self.mainPath = os.path.join(self.mainPath,dirname)
    
            self.request.sendall(self.mainPath.encode('utf-8'))
    View Code

    到此为止,可以简单的完成上传任务,如果需要添加任务,只需要在ftp_client.py和server.py下面定义新的函数进行交互就可以了。

  • 相关阅读:
    提交代码报错不同方式
    pow log 与 (int)
    优先队列的创建
    积性函数
    静态主席树,动态主席树(一种可持久化线段树)
    codeblocks 输入、输出文件的位置
    后缀自动机
    BellmanFord 最短路
    struct
    hdu1501 动态规划
  • 原文地址:https://www.cnblogs.com/smart-zihan/p/9614771.html
Copyright © 2011-2022 走看看