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


Posted in Python onMarch 27, 2020

一、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 random模块(获取随机数)常用方法和使用例子
May 13 Python
Python自动化部署工具Fabric的简单上手指南
Apr 19 Python
Python实现Logger打印功能的方法详解
Sep 01 Python
Python语言生成水仙花数代码示例
Dec 18 Python
python十进制和二进制的转换方法(含浮点数)
Jul 07 Python
python 自动去除空行的实例
Jul 24 Python
python使用rpc框架gRPC的方法
Aug 24 Python
python实现感知机线性分类模型示例代码
Jun 02 Python
python异常处理try except过程解析
Feb 03 Python
django 前端页面如何实现显示前N条数据
Mar 16 Python
python实现在列表中查找某个元素的下标示例
Nov 16 Python
利用Pycharm连接服务器的全过程记录
Jul 01 Python
使用python从三个角度解决josephus问题的方法
Mar 27 #Python
解决django接口无法通过ip进行访问的问题
Mar 27 #Python
Django 实现将图片转为Base64,然后使用json传输
Mar 27 #Python
python实现简单坦克大战
Mar 27 #Python
Django实现从数据库中获取到的数据转换为dict
Mar 27 #Python
Python生成器实现简单&quot;生产者消费者&quot;模型代码实例
Mar 27 #Python
python数据库编程 Mysql实现通讯录
Mar 27 #Python
You might like
php关联数组快速排序的方法
2015/04/17 PHP
javascript 继承实现方法
2009/08/26 Javascript
javascript去掉前后空格的实例
2013/11/07 Javascript
js脚本获取webform服务器控件的方法
2014/05/16 Javascript
Javascript闭包(Closure)详解
2015/05/05 Javascript
JS+CSS实现美化的下拉列表框效果
2015/08/11 Javascript
JS跨域解决方案之使用CORS实现跨域
2016/04/14 Javascript
jQuery通过deferred对象管理ajax异步
2016/05/20 Javascript
nodejs读取并去重excel文件
2018/04/22 NodeJs
Node.js模拟发起http请求从异步转同步的5种用法
2018/09/26 Javascript
AngularJS $http post 传递参数数据的方法
2018/10/09 Javascript
Node.js中package.json中库的版本号(~和^)
2019/04/02 Javascript
Javascript 关于基本类型和引用类型的个人理解
2019/11/01 Javascript
Vue3项目打包后部署到服务器 请求不到后台接口解决方法
2020/02/06 Javascript
[01:04:22]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 IG vs EG
2018/04/01 DOTA
改进Django中的表单的简单方法
2015/07/17 Python
python 判断是否为正小数和正整数的实例
2017/07/23 Python
在交互式环境中执行Python程序过程详解
2019/07/12 Python
利用python实现PSO算法优化二元函数
2019/11/13 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
用canvas画心电图的示例代码
2018/09/10 HTML / CSS
美国著名的婴儿学步鞋老品牌:Robeez
2016/08/20 全球购物
美国最大的在线水培用品商店:GrowersHouse.com
2018/08/14 全球购物
Redbubble法国:由独立艺术家设计的独特产品
2019/01/08 全球购物
英国蛋糕装饰用品一站式商店:Craft Company
2019/03/18 全球购物
澳大利亚优惠网站:Deals.com.au
2019/07/02 全球购物
Spotahome意大利:公寓和房间出租
2020/02/21 全球购物
C有"按引用传递"吗
2016/09/06 面试题
医校毕业生自我鉴定
2014/01/25 职场文书
测试工程师职业规划书
2014/02/06 职场文书
高等教育专业自荐信范文
2014/03/26 职场文书
小学班主任培训心得体会
2016/01/07 职场文书
Nginx设置日志打印post请求参数的方法
2021/03/31 Servers
MySQL提升大量数据查询效率的优化神器
2022/07/07 MySQL
设置IIS Express并发数
2022/07/07 Servers
Win11使用CAD卡顿或者致命错误怎么办?Win11无法正常使用CAD的解决方法
2022/07/23 数码科技