十八.Python模拟FTP文件上传

Python 模拟FTP断点续传并发服务器

 

#配置文件

#服务器配置文件

[server_config]
ip=127.0.0.1
port=8006
buffersize=1024
encoding=utf-8

#服务器用户数据 

[tom]
username=tom
password=123456
[alex]
username=alex
password=123456

 

#FTP服务器代码

#程序入口
import optparse
import sys,os
#os.path.dirname 获取文件的文件夹路径
path=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(path)
from core import main
class ftt_server:
   def __init__(self):
      self.option = optparse.OptionParser()
      self.option.add_option("-i", "--ip", dest="ip")
      self.option.add_option("-p", "--port", dest="port")
      self.opt, self.args = self.option.parse_args()
      self.one()
   def one(self):
      main.main(self.opt, self.args)

if __name__=="__main__":
   ftt_server()

#服务器监听程序
import socketserver
import optparse
import configparser
import os
from core import server
class main():
    def __init__(self,opt,args):
        args=args
        self.option=opt
        self.config=configparser.ConfigParser()
        self.config.read(os.path.dirname(os.path.dirname(__file__))+"/conf/config.ini")
        self.server=server
        self.BaseDir=os.path.dirname(os.path.dirname(__file__))
        self.validate(opt, args)
    def validate(self, options, args):
        cmd=args[0]
        if hasattr(self,cmd):
            fun=getattr(self,cmd)
            fun()
    def start(self):
        ip=self.option.ip
        port=self.option.port
        if ip=="":
            ip=self.getConfig("server_config","ip")
        if port=="":
            port=self.getConfig("server_config","port")
        print("server start Successful!")
        self.sock_ser=socketserver.ThreadingTCPServer((ip,int(port)),self.server.server_handler)
        self.sock_ser.serve_forever()

    def help(self):
        pass

    def getConfig(self,section,attribute):
        return self.config.read(section,attribute)


#服务器主程序
import socketserver
import configparser
import os
import json
import sys
class server_handler(socketserver.BaseRequestHandler):
    def handle(self):
        self.config_name="server_config"
        self.BaseDir=os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
        self.config_Path=os.path.join(self.BaseDir,"conf","config.ini")
        self.user_config=os.path.join(self.BaseDir,"conf","user.ini")
        self.buffersize=int(self.getIni(self.config_Path,self.config_name,"buffersize"))
        self.encoding=self.getIni(self.config_Path,self.config_name,"encoding")
        self.currenSize=0
        data = self.request.recv(self.buffersize).decode(self.encoding)
        data = json.loads(data)
        print(data)
        fun = data["action"]
        if fun=="login":
            con=configparser.ConfigParser()
            con.read(self.user_config)
            if con.has_section(data["user"]):
                if con.get(data["user"],"password")==data["password"]:
                    self.currenDir=data["user"]
                    self.request.sendall("504".encode("utf-8"))
                    self.name=data["user"]
                    self.home=os.path.join(self.BaseDir, "home",data["user"])
                    self.currenDir=self.home
                    self.interception()
                else:
                    self.request.sendall("404".encode("utf-8"))
    

    def getIni(self,path,section,attribute):
        conf = configparser.ConfigParser()
        conf.read(path)
        return conf.get(section, attribute)
    #交互
    def interception(self):
        while 1:
            print("wait recv....")
            data=self.request.recv(self.buffersize)
            data=json.loads(data)
            print(data)
            fun=data["action"]
            if hasattr(self,fun):
                func=getattr(self,fun)
                func(**data)
            else:
                self.request.sendall("400".encode("utf-8"))
    #cd文件夹切换功能
    def cd(self,**kwargs):
        position=kwargs["position"]
        if position=="../":
            self.currenDir =os.path.dirname(self.currenDir)
        else:
            self.currenDir=os.path.join(self.currenDir,position)
        self.request.sendall(os.path.basename(self.currenDir).encode(self.encoding))
    #创建文件夹功能
    def mkdir(self,**kwargs):
        print(kwargs)
        position=kwargs["position"]
        mkfile=os.path.join(self.currenDir,position)
        try:
            if "/" in position or "\\" in position:
                os.makedirs(mkfile)
            else:
                os.mkdir(mkfile)
        except Exception as e:
            self.request.sendall("605".encode(self.encoding))
        self.request.sendall("606".encode(self.encoding))
    #显示当前文件夹内容
    def ls(self,**kwargs):
        dir_con=os.listdir(self.currenDir)
        self.request.sendall(str(dir_con).encode("utf-8"))
    #文件断点续传功能
    def put(self,**kwargs):
        file_name=kwargs["file_name"]
        file_size=kwargs["file_size"]
        target=kwargs["target"]
        self.target_file=os.path.join(self.currenDir,target,file_name)
        if os.path.exists(self.target_file):
            self.currenSize=os.stat(self.target_file).st_size
            if self.currenSize>=file_size:
                self.request.sendall("801".encode(self.encoding))
                return
            else:
                self.request.sendall("802".encode(self.encoding))
                data=self.request.recv(self.buffersize).decode(self.encoding)
                if data=="Y":
                    f = open(self.target_file, "ab")
                    self.request.sendall(str(self.currenSize).encode(self.encoding))
                else:
                    f = open(self.target_file, "wb")
        else:
            f = open(self.target_file, "wb")
            self.request.sendall("803".encode("utf-8"))

        while self.currenSize<file_size:
            data=self.request.recv(self.buffersize)
            f.write(data)
            self.currenSize+=len(data)
            self.progess(self.currenSize, file_size)
    #文件上传进度
    def progess(self,curren,total):
        rate = int(curren / total * 100)
        if rate > 0:
            st=sys.stdout
            st.write("%s%% %s \r\n"%(rate,"*"*rate))
            st.flush()
            if rate==100:
                print("upload finish!")


#FTP客户端

#配置文件

[client_config]
buffer_size=1024

#客户端代码

#FTP客户端程序
from socket import *
import sys,os
import optparse
import json
import configparser
path=os.path.dirname(os.path.dirname(__file__))
sys.path.append(path)

#状态字典
dicts={"504":"登陆成功!",
      "404":"用户或者密码有误!登陆失败!",
      "400":"Input Error",
       "606":"create success",
       "605":"create fail",
       "801":"the file is existing",
       "802":"the file is existing,but not enough",
       "803":"the file start upload..."
      }

class client_handler:
    def __init__(self):
        self.option=optparse.OptionParser()
        self.option.add_option("-i", "--ip", dest="ip")
        self.option.add_option("-p", "--port", dest="port")
        self.option.add_option("-u", "--user", dest="username")
        self.option.add_option("-P", "--password", dest="password")
        self.conf = configparser.ConfigParser()
        self.Base_Dir=os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
        self.buffersize= int(self.bufferSize())
        self.size_file=0
        options, args = self.option.parse_args()
        self.task(options,args)
    def task(self, options, args):
        port=options.port
        if int(port)>0 and int(port)<65535:
            self.make_connection(options,args)
        else:
            exit("the port is in 0 and 65535!")
    def make_connection(self, options, args):
        self.sclient = socket(AF_INET, SOCK_STREAM)
        self.sclient.connect((options.ip, int(options.port)))
        self.login()
    def login(self):
        name=input("请输入用户名>>")
        password=input("请输入密码>>")
        self.json = {"action": "login", "user": name, "password": password}
        self.sclient.send(json.dumps(self.json).encode("utf-8"))
        data=self.sclient.recv(self.buffersize).decode("utf-8")
        # print(data)
        if data=="504":
            self.name=name
            print(dicts[data])
            while 1:
                code=input("[%s]"%self.name)
                cmd_list=code.split()
                if hasattr(self,cmd_list[0]):
                    fun=getattr(self,cmd_list[0])
                    fun(*cmd_list)
        else:
            print(dicts[data])
    def bufferSize(self):
        self.conf_path=os.path.join(self.Base_Dir,"conf","config.ini")
        self.conf.read(self.conf_path)
        return self.conf.get("client_config", "buffer_size")

    def put(self,*cmd_list):
        # print("put...")
        action,location,target=cmd_list
        file_name=os.path.basename(location)
        file_size=os.stat(location).st_size
        data={"action":action,
              "file_name":file_name,
              "file_size":file_size,
              "target":target}
        self.sclient.sendall(json.dumps(data).encode("utf-8"))
        data=self.sclient.recv(self.buffersize).decode("utf-8")
        self.parseNum(data)
        if data=="801":
            return
        elif data=="802":
            choice=input("the file is existing,but not enough,is continue?<Y/N>")
            if choice.upper()=="Y":
                self.sclient.sendall(choice.upper().encode("utf-8"))
                self.size_file =int(self.sclient.recv(self.buffersize).decode("utf-8"))
            else:
                self.sclient.sendall(choice.upper().encode("utf-8"))
        elif data=="803":
            pass
        f=open(location,"rb")
        f.seek(self.size_file)
        while self.size_file<file_size:
            fdata=f.read(self.buffersize)
            self.sclient.sendall(fdata)
            self.size_file+=len(fdata)
            self.progess(self.size_file, file_size)
    def cd(self,*cmd_list):
        # print("cd...")
        action,position=cmd_list
        data={"action":action,
              "position":position}
        data=json.dumps(data)
        self.sclient.sendall(data.encode("utf-8"))
        data=self.sclient.recv(self.buffersize).decode("utf-8")
        self.name=data
    def ls(self,*cmd_list):
        action=cmd_list[0]
        data={"action":action}
        data=json.dumps(data)
        self.sclient.sendall(data.encode("utf-8"))
        con=self.sclient.recv(self.buffersize).decode("utf-8")
        con=list(con)
        for i in con:
            print(i,end="\r")
    def mkdir(self,*cmd_list):
        print("mkdir...")
        action,position=cmd_list
        data={"action":action,
              "position":position
              }
        data=json.dumps(data)
        self.sclient.sendall(data.encode("utf-8"))
        con=self.sclient.recv(self.buffersize).decode("utf-8")
        print(dicts[con])
    def parseNum(self,st):
        print(dicts[st])
    def progess(self,curren,total):
        rate=int(curren/total*100)
        if rate > 0:
            st=sys.stdout
            st.write("%s%% %s\r\n"%(rate,"*"*rate))
            st.flush()
            if rate==100:
                print("upload finish!")

#程序入口
if __name__=="__main__":
    client_handler()








启动

#服务器启动
python ftp_server start -i 127.0.0.1 -p 8006

#客户端启动
python ftp_client -i 127.0.0.1 -p 8006

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值