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 相关文章推荐
pycharm 使用心得(四)显示行号
Jun 05 Python
浅析Python中将单词首字母大写的capitalize()方法
May 18 Python
django之session与分页(实例讲解)
Nov 13 Python
python 基本数据类型占用内存空间大小的实例
Jun 12 Python
Python3非对称加密算法RSA实例详解
Dec 06 Python
在pycharm中设置显示行数的方法
Jan 16 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
Jan 29 Python
Pandas库之DataFrame使用的学习笔记
Jun 21 Python
python sorted函数原理解析及练习
Feb 10 Python
基于Python正确读取资源文件
Sep 14 Python
Python监听剪切板实现方法代码实例
Nov 11 Python
Python实现钉钉/企业微信自动打卡的示例代码
Feb 02 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开发框架总结收藏
2008/04/24 PHP
PHP file_exists问题杂谈
2012/05/07 PHP
浅谈PHP中类和对象的相关函数
2017/04/26 PHP
jQuery 加上最后自己的验证
2009/11/04 Javascript
js中将字符串转换成json的三种方式
2011/01/12 Javascript
当鼠标滑过文本框自动选中输入框内容的JS代码分享
2013/11/26 Javascript
javascript修改IMG标签的src问题
2014/03/28 Javascript
JavaScript获取图片像素颜色并转换为box-shadow显示
2016/03/11 Javascript
jQuery 实现评论等级好评差评特效
2016/05/06 Javascript
js中获取键盘事件的简单实现方法
2016/10/10 Javascript
jQuery实现倒计时(倒计时年月日可自己输入)
2016/12/02 Javascript
微信小程序 解决swiper不显示图片的方法
2017/01/04 Javascript
详解微信小程序入门五: wxml文件引用、模版、生命周期
2017/01/20 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
Postman无法正常返回结果问题解决
2020/08/28 Javascript
python根据给定文件返回文件名和扩展名的方法
2015/03/27 Python
Django的URLconf中使用缺省视图参数的方法
2015/07/18 Python
在Python中关于使用os模块遍历目录的实现方法
2019/01/03 Python
python实现ftp文件传输系统(案例分析)
2020/03/20 Python
Python如何爬取b站热门视频并导入Excel
2020/08/10 Python
python利用线程实现多任务
2020/09/18 Python
美国最大的城市服装和运动鞋零售商:Jimmy Jazz
2016/11/19 全球购物
荷兰牛仔裤网上商店:Jeans Centre
2018/04/03 全球购物
莱德杯高尔夫欧洲官方商店:Ryder Cup Shop
2019/08/14 全球购物
鞋类设计与工艺专业销售求职信
2013/11/01 职场文书
行政主管职责范本
2014/03/07 职场文书
求职信结尾怎么写
2014/05/26 职场文书
今冬明春火灾防控工作方案
2014/05/29 职场文书
审计局2014法制宣传日活动总结
2014/11/01 职场文书
婚育证明格式
2015/06/17 职场文书
2016幼儿园中班开学寄语
2015/12/03 职场文书
《正比例》教学反思
2016/02/23 职场文书
小学四年级班务总结该怎么写?
2019/08/16 职场文书
mysql 如何获取两个集合的交集/差集/并集
2021/06/08 MySQL
MySQL 用 limit 为什么会影响性能
2021/09/15 MySQL
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
2022/03/22 MySQL