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中getaddrinfo()基本用法实例分析
Jun 28 Python
Python实现的堆排序算法原理与用法实例分析
Nov 22 Python
Python爬虫实现百度图片自动下载
Feb 04 Python
python3+PyQt5+Qt Designer实现扩展对话框
Apr 20 Python
Python 统计字数的思路详解
May 08 Python
Python实现字典排序、按照list中字典的某个key排序的方法示例
Dec 18 Python
Python2.7实现多进程下开发多线程示例
May 31 Python
pycharm新建一个python工程步骤
Jul 16 Python
python 解决flask uwsgi 获取不到全局变量的问题
Dec 22 Python
pytorch-RNN进行回归曲线预测方式
Jan 14 Python
使用pytorch实现论文中的unet网络
Jun 24 Python
用Python生成会跳舞的美女
Jan 18 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通过array_unshift函数添加多个变量到数组前端的方法
2015/03/18 PHP
laravel学习教程之存取器
2016/07/30 PHP
TP5多入口设置实例讲解
2020/12/15 PHP
用Greasemonkey 脚本收藏网站会员信息到本地
2009/10/26 Javascript
De facto standard 世界上不可思议的事实标准
2010/08/29 Javascript
JavaScript NodeTree导航栏(菜单项JSON类型/自制)
2013/02/01 Javascript
IE下window.onresize 多次调用与死循环bug处理方法介绍
2013/11/12 Javascript
简介JavaScript中getUTCMonth()方法的使用
2015/06/10 Javascript
jQuery插件 Jqplot图表实例
2016/06/18 Javascript
fullpage.js全屏滚动插件使用实例
2016/09/06 Javascript
JavaScript限定范围拖拽及自定义滚动条应用(3)
2017/05/17 Javascript
React学习笔记之列表渲染示例详解
2017/08/22 Javascript
说说AngularJS中的$parse和$eval的用法
2017/09/14 Javascript
vue项目实现github在线预览功能
2018/06/20 Javascript
纯JS实现的读取excel文件内容功能示例【支持所有浏览器】
2018/06/23 Javascript
Angular6 写一个简单的Select组件示例
2018/08/20 Javascript
微信小程序引用iconfont图标的方法
2018/10/22 Javascript
新手简单了解vue
2019/05/29 Javascript
layui实现图片虚拟路径上传,预览和删除的例子
2019/09/25 Javascript
使用JS监听键盘按下事件(keydown event)
2019/11/07 Javascript
keep-Alive搭配vue-router实现缓存页面效果的示例代码
2020/06/24 Javascript
js实现有趣的倒计时效果
2021/01/19 Javascript
python控制台显示时钟的示例
2014/02/24 Python
Python网络爬虫实例讲解
2016/04/28 Python
Python将多份excel表格整理成一份表格
2018/01/03 Python
python飞机大战pygame游戏背景设计详解
2019/12/17 Python
pytorch 把图片数据转化成tensor的操作
2021/03/04 Python
荷兰皇家航空公司官方网站:KLM Royal Dutch Airlines
2017/12/07 全球购物
意大利高端时尚买手店:Stefania Mode
2018/03/01 全球购物
机械专业应届生求职信
2013/12/12 职场文书
乡镇三严三实学习心得体会
2014/10/13 职场文书
护士自我推荐信范文
2015/03/24 职场文书
2015年乡镇工会工作总结
2015/05/19 职场文书
队名及霸气口号大全
2015/12/25 职场文书
python使用PySimpleGUI设置进度条及控件使用
2021/06/10 Python
Android实现图片九宫格
2022/06/28 Java/Android