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

Python Socketserver实现FTP文件上传下载代码实例,第1张

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

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

  目录结构

    

1、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"}

到这里差不多就没了,

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/3230337.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-10-04
下一篇 2022-10-04

发表评论

登录后才能评论

评论列表(0条)

保存