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版
Dec 07 Python
详解Python的Django框架中的模版相关知识
Jul 15 Python
深入解析Python编程中JSON模块的使用
Oct 15 Python
Python中使用Queue和Condition进行线程同步的方法
Jan 19 Python
python3 模拟登录v2ex实例讲解
Jul 13 Python
深入学习Python中的上下文管理器与else块
Aug 27 Python
Python3随机漫步生成数据并绘制
Aug 27 Python
Django实现表单验证
Sep 08 Python
python多进程使用及线程池的使用方法代码详解
Oct 24 Python
python3 实现对图片进行局部切割的方法
Dec 05 Python
python使用pipeline批量读写redis的方法
Feb 18 Python
python实现上传文件到linux指定目录的方法
Jan 03 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
ThinkPHP模板中判断volist循环的最后一条记录的验证方法
2014/07/01 PHP
PHP彩蛋信息介绍和阻止泄漏的方法(隐藏功能)
2014/08/06 PHP
PHP命名空间(namespace)的动态访问及使用技巧
2014/08/18 PHP
thinkphp判断访客为手机端或PC端的方法
2014/11/24 PHP
写一段简单的PHP建立文件夹代码
2015/01/06 PHP
Zend Framework生成验证码并实现验证码验证功能(附demo源码下载)
2016/03/22 PHP
PHP面向对象程序设计之对象生成方法详解
2016/12/02 PHP
Laravel框架用户登陆身份验证实现方法详解
2017/09/14 PHP
有趣的javascript数组定义方法
2010/09/10 Javascript
in.js 一个轻量级的JavaScript颗粒化模块加载和依赖关系管理解决方案
2011/07/26 Javascript
简单js代码实现selece二级联动(推荐)
2014/02/18 Javascript
JavaScript随机打乱数组顺序之随机洗牌算法
2016/08/02 Javascript
Vue.js开发环境搭建
2016/11/10 Javascript
详解Node.js access_token的获取、存储及更新
2017/06/20 Javascript
mongodb初始化并使用node.js实现mongodb操作封装方法
2019/04/02 Javascript
layui 数据表格+分页+搜索+checkbox+缓存选中项数据的方法
2019/09/21 Javascript
基于vue-cli3创建libs库的实现方法
2019/12/04 Javascript
Vue 图片压缩并上传至服务器功能
2020/01/15 Javascript
js、jquery实现列表模糊搜索功能过程解析
2020/03/27 jQuery
JavaScript面向对象核心知识与概念归纳整理
2020/05/09 Javascript
JavaScript随机数的组合问题案例分析
2020/05/16 Javascript
简单谈谈offsetleft、offsetTop和offsetParent
2020/12/04 Javascript
[54:25]Ti4 循环赛第三日LGD vs MOUZ
2014/07/12 DOTA
Django中模版的子目录与include标签的使用方法
2015/07/16 Python
由浅入深讲解python中的yield与generator
2017/04/05 Python
django中的setting最佳配置小结
2017/11/21 Python
解决Tensorflow安装成功,但在导入时报错的问题
2018/06/13 Python
keras的load_model实现加载含有参数的自定义模型
2020/06/22 Python
创立科技Java面试题
2015/11/29 面试题
售后服务经理岗位职责范本
2014/02/22 职场文书
实验心得体会
2014/09/05 职场文书
企业党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
幼师求职自荐信
2015/03/26 职场文书
《称赞》教学反思
2016/02/17 职场文书
员工试用期工作总结
2019/06/20 职场文书
SQLServer权限之只开启创建表权限
2022/04/12 SQL Server