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解决汉字编码问题:Unicode Decode Error
Jan 19 Python
Django2.1集成xadmin管理后台所遇到的错误集锦(填坑)
Dec 20 Python
ZABBIX3.2使用python脚本实现监控报表的方法
Jul 02 Python
python增加图像对比度的方法
Jul 12 Python
Python中的延迟绑定原理详解
Oct 11 Python
python中图像通道分离与合并实例
Jan 17 Python
python GUI库图形界面开发之PyQt5窗口控件QWidget详细使用方法
Feb 26 Python
PyCharm GUI界面开发和exe文件生成的实现
Mar 04 Python
django的模型类管理器——数据库操作的封装详解
Apr 01 Python
如何实现在jupyter notebook中播放视频(不停地展示图片)
Apr 23 Python
python中Tkinter 窗口之输入框和文本框的实现
Apr 12 Python
pytorch中F.avg_pool1d()和F.avg_pool2d()的使用操作
May 22 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实现mysql数据库备份类
2008/03/20 PHP
关于php循环跳出的问题
2013/07/01 PHP
php动态生成版权所有信息的方法
2015/03/24 PHP
php实现session共享的实例方法
2019/09/19 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
2019/11/21 PHP
Javascript中arguments对象详解
2014/10/22 Javascript
JS函数this的用法实例分析
2015/02/05 Javascript
js实现网页右上角滑出会自动消失大幅广告的方法
2015/02/27 Javascript
jquery简单实现图片切换效果的方法
2015/05/12 Javascript
js图片翻书效果代码分享
2015/08/20 Javascript
js实现的tab标签切换效果代码分享
2015/08/25 Javascript
Jquery实现跨域异步上传文件总结
2017/02/03 Javascript
vue项目tween方法实现返回顶部的示例代码
2018/03/02 Javascript
vue 实现的树形菜的实例代码
2018/03/19 Javascript
react配合antd组件实现的管理系统示例代码
2018/04/24 Javascript
vue地址栏直接输入路由无效问题的解决
2018/11/15 Javascript
VUE中使用MUI方法
2019/02/12 Javascript
jQuery删除/清空指定元素的所有子节点实例代码
2019/07/04 jQuery
使用layui的layer组件做弹出层的例子
2019/09/27 Javascript
JS前端模块化原理与实现方法详解
2020/03/17 Javascript
Vue 修改网站图标的方法
2020/12/31 Vue.js
零基础写python爬虫之使用Scrapy框架编写爬虫
2014/11/07 Python
Python实现ssh批量登录并执行命令
2016/10/25 Python
Django视图扩展类知识点详解
2019/10/25 Python
Python算法的时间复杂度和空间复杂度(实例解析)
2019/11/19 Python
使用PyTorch将文件夹下的图片分为训练集和验证集实例
2020/01/08 Python
如何通过Python实现RabbitMQ延迟队列
2020/11/28 Python
用CSS3写的模仿iPhone中的返回按钮
2015/04/04 HTML / CSS
详解CSS3中@media的实际使用
2015/08/04 HTML / CSS
纽约服装和生活方式品牌:Saturdays NYC
2017/08/13 全球购物
土耳其时尚购物网站:Morhipo
2017/09/04 全球购物
世界上最大的高分辨率在线图片库:Alamy
2018/07/07 全球购物
普通PHP程序员笔试题
2016/01/01 面试题
最新英语专业学生求职信范文
2013/09/21 职场文书
老师自我鉴定范文
2013/12/25 职场文书
学习弘扬焦裕禄精神心得体会
2016/01/23 职场文书