Python Socketserver实现FTP文件上传下载代码实例

2020-09-24 0 906

一、Socketserver实现FTP,文件上传下载

  目录结构

    Python Socketserver实现FTP文件上传下载代码实例

1、socketserver实现ftp文件上传下载,可以同时多用户登录、上传、下载

  效果图:

  Python Socketserver实现FTP文件上传下载代码实例

Python Socketserver实现FTP文件上传下载代码实例

Python Socketserver实现FTP文件上传下载代码实例

二、上面只演示了下载,上传也是一样的,来不及演示了,上代码

1、客户端

import socket,hashlib,os,json,sys,time
class Ftpclient(object):
  def __init__(self):
    self.client = socket.socket()

  def connect(self,ip,port):
    self.client.connect((ip, port))
  def help(self):
    msg=\'\'\'
    ls 

    pwd 
    
    cd ..
    
    get filename
    
    put filename
    
    \'\'\'
    print(msg)


  def interactive(self):
    \"\"\"
    客户端入口
    :return:
    \"\"\"
    while True:
      verify = self.authenticate() #服务器端认证
      if verify:
        while True:
          cmd = input(\'输入命令 >>\').strip()
          if len(cmd) == 0:continue
          cmd_str = cmd.split()[0]
          if hasattr(self,\'cmd_%s\' %cmd_str):
            func = getattr(self,\'cmd_%s\' %cmd_str)
            func(cmd)
          else:
            self.help()


  def cmd_put(self,*args):
    \"\"\"
    上传文件
    :param args:
    :return:
    \"\"\"
    cmd_solit = args[0].split()
    start_time = self.alltime() # 开始时间
    if len(cmd_solit) > 1:
      filename = cmd_solit[1]
      if os.path.isfile(filename):
        filesize = os.stat(filename).st_size
        msg_dic = {
          \'filename\':filename,
          \'size\':filesize,
          \'overridden\':True,
          \'action\':cmd_solit[0]
        }

        self.client.send( json.dumps(msg_dic).encode(\'utf-8\'))
        server_respinse=self.client.recv(1024) #防止粘包,等服务器确认返回
        print(\'文件开始上传\',server_respinse)
        client_size = 0
        f = open(filename,\'rb\')
        for line in f:
          client_size += self.client.send(line)
          self.processBar(client_size,filesize) #进度条
        else:
          print(\'文件传输完毕,大小为 %s\'%client_size)
          end_time = self.alltime()       # 结束时间
          print(\'本次上传花费了%s 秒\'%self.alltime(end_time,start_time))
          f.close()
      else:
        print(filename,\'文件不存在\')
    else:
      print(\'输入有误!\')


  def cmd_get(self,*args):
    \"\"\"
    下载文件
    :param args:
    :return:
    \"\"\"
    cmd_solit = args[0].split()
    start_time = self.alltime() # 开始时间
    filename = cmd_solit[1]
    if len(cmd_solit) > 1:
      msg_dic = {
        \'filename\': filename,
        \'size\': \'\',
        \'overridden\': True,
        \'action\': cmd_solit[0],
        \'file_exist\':\'\'
      }
      self.client.send(json.dumps(msg_dic).encode(\'utf-8\'))
      self.data = self.client.recv(1024).strip()

      cmd_dic = json.loads(self.data.decode(\'utf-8\'))
      print(cmd_dic)
      if cmd_dic[\'file_exist\']:
        if os.path.isfile(filename):
          f = open(filename + \'.new\', \'wb\')
        else:
          f = open(filename, \'wb\')

        self.client.send(b\'200 ok\')   #防止粘包,等服务器确认返回
        client_size = 0
        filesize = cmd_dic[\'size\']
        m = hashlib.md5()
        while client_size < filesize:
          data=self.client.recv(1024)
          f.write(data)
          client_size +=len(data)
          m.update(data)
          self.processBar(client_size, filesize)
        else:
          print(\'下载完毕\')
          end_time = self.alltime()  # 结束时间
          print(\'本次下载花费了%s 秒\' % self.alltime(end_time, start_time))
          f.close()
          new_file_md5 = m.hexdigest()
          server_file_md5 = self.client.recv(1024)
          print(\'MD5\', server_file_md5,new_file_md5)

      else:
        print(\'下载的 %s文件不存在\'%filename)

    else:
      print(\'输入有误!\')


  def cmd_dir(self,*arge):
    cmd_solit = arge[0].split()
    if len(cmd_solit) > 0:
      msg_dic = {
        \'action\': cmd_solit[0]
      }
      self.client.send(json.dumps(msg_dic).encode())
      cmd_dir = self.client.recv(1024)
      print(cmd_dir.decode())

    else:
      print(\'输入错误!\')



  def alltime(self,*args):
    \"\"\"
    计算上传、下载时间
    :param args:
    :return:
    \"\"\"
    if args:
      return round(args[0] - args[1])
    else:
      return time.time()


  def processBar(self,num, total):
    \"\"\"
    进度条
    :param num:文件总大小
    :param total: 已存入文件大小
    :return:
    \"\"\"
    rate = num / total
    rate_num = int(rate * 100)
    if rate_num == 100:
      r = \'\\r%s>%d%%\\n\' % (\'=\' * int(rate_num /3), rate_num,)
    else:
      r = \'\\r%s>%d%%\' % (\'=\' * int(rate_num /3), rate_num,)
    sys.stdout.write(r)
    sys.stdout.flush


  def authenticate(self):
    \"\"\"
    用户加密认证
    :return:
    \"\"\"
    username = input(\'输入用户名:>>\')
    password = input(\'输入密码:>>\')
    m = hashlib.md5()
    if len(username) > 0 and len(password) >0:
      username = \'\'.join(username.split())
      password = \'\'.join(password.split())
      m.update(username.encode(\'utf-8\'))
      m.update(password.encode(\'utf-8\'))

      m = {
        \'username\':username,
        \'password\':password,
        \'md5\':m.hexdigest()
      }
      self.client.send(json.dumps(m).encode(\'utf-8\'))
      server_user_md5 = self.client.recv(1024).strip()
      print(server_user_md5.decode())
      if server_user_md5.decode() == \'success\':
        print(\'登录成功!\')
        return \'ok\'
      else:
        print(\'用户名密码错误!\')
    else:
      print(\'请输入用户名密码\')

f = Ftpclient()
f.connect(\'localhost\',9999)
f.interactive()

2、服务器端

import socketserver,json,os,hashlib,sys,paramiko
import settings
class Mysocketserver(socketserver.BaseRequestHandler):
  def put(self,*args):
    \'\'\'
    接受客户端上传文件
    :return:
    \'\'\'
    cmd_dic = args[0]
    filename = cmd_dic[\'filename\'] #获取文件名
    filesize= cmd_dic[\'size\']    #获取文件大小(字节)

    if os.path.isfile(filename):  #判断文件是否存在
      f = open(filename + \'.new\',\'wb\')
    else:
      f = open(filename, \'wb\')

    self.request.send(b\'200 ok\')  #防止粘包
    print(\'%s 文件开始上传\' % self.client_address[0])
    received_size = 0
    while received_size < filesize:
      data = self.request.recv(1024)
      f.write(data)
      received_size += len(data)
    else:
      print(\'文件传输完毕\',filename)


  def get(self, *args):
    \'\'\'
    客户端下载文件
    :return:
    \'\'\'
    msg_dic = {
      \'filename\': \'\',
      \'size\': \'\',
      \'overridden\': True,
      \'action\': \'\',
      \'file_exist\': \'\'
    }

    cmd_solit = args[0]
    filename = cmd_solit[\'filename\']
    file_exist = os.path.isfile(filename)
    msg_dic[\'file_exist\'] = file_exist
    print(file_exist)
    if file_exist:
      filesize = os.stat(filename).st_size

      msg_dic[\'filename\'] = filename
      msg_dic[\'size\'] = filesize
      msg_dic[\'action\'] = cmd_solit[\'action\']

      self.request.send(json.dumps(msg_dic).encode(\'utf-8\'))
      server_respang = self.request.recv(1024) #防止粘包
      print(\'开始传输\',server_respang)
      f = open(filename,\'rb\')
      m = hashlib.md5()
      for lien in f:
        m.update(lien)
        self.request.send(lien)
      else:
        print(\'传输完成\')
        f.close()
        self.request.send(m.hexdigest().encode())
    else:
      print(\'文件不存在\')
      self.request.send(json.dumps(msg_dic).encode(\'utf-8\'))
  def client_authentication(self):
    \"\"\"
    客户端认证
    :return:
    \"\"\"
    self.client_user= self.request.recv(1024).strip()
    client_xinxi = json.loads(self.client_user.decode(\'utf-8\'))
    try:
      with open(settings.school_db_file + client_xinxi[\'username\'],\'rb\') as f:
        data = json.load(f)
        if data[\'md5\'] == client_xinxi[\'md5\']: #判断用户输入是否和服务器端MD5是否一致
          print(\'验证成功!\')
          self.request.send(\'success\'.encode())
          return \'success\'
        else:
          self.request.send(\'error\'.encode())
    except Exception as e:
      print(\'没有此用户\',e)
      self.request.send(\'error\'.encode())
  def dir(self,*args):
    \"\"\"
    查看目录
    :param args:
    :return:
    \"\"\"
    cmd_split = args[0]
    dd=cmd_split[\'action\']
    result_os = os.popen(dd).read()
    self.request.send(result_os.encode())

  def handle(self):
    \"\"\"
    服务器端入口
    :return:
    \"\"\"
    while True:
      try:
        success = self.client_authentication()
        if success:
          self.data=self.request.recv(1024).strip()
          cmd_dic = json.loads(self.data.decode(\'utf-8\'))
          action = cmd_dic[\'action\']
          if hasattr(self,action):
            func = getattr(self,action)
            func(cmd_dic)
      except ConnectionResetError as e:
        print(\'连接断开\',self.client_address[0])
        break
if __name__ == \'__main__\':

  HOST,PORT=\'localhost\',9999
  server=socketserver.ThreadingTCPServer((HOST,PORT),Mysocketserver)
  server.serve_forever()

settings.py 文件

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DB_FILE = os.path.join(BASE_DIR, \"data\\\\\")
school_db_file = os.path.join(DB_FILE)
print(school_db_file)

data里两个做测试的文件,

alex 文件内容:
 {\”username\”: \”alex\”, \”password\”: \”123456\”, \”md5\”: \”94e4ccf5e2749b0bfe0428603738c0f9\”}

kml123456文件内容:
{\”username\”: \”kml123456\”, \”password\”: \”123456\”,\”md5\”: \”a791650e70ce08896e3dafbaa7598c26\”}

到这里差不多就没了,

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。

遇见资源网 Python Python Socketserver实现FTP文件上传下载代码实例 http://www.ox520.com/25119.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务