Python Socketserver实现FTP文件上传下载代码实例
作者:Kong-Ming 发布时间:2022-10-10 11:03:04
标签:Python,Socket,server,ftp,上传,下载
一、Socketserver实现FTP,文件上传、下载
目录结构
1、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"}
到这里差不多就没了,
来源:https://www.cnblogs.com/km-thonder/p/12579302.htm
0
投稿
猜你喜欢
- 首先恭喜月影,当然希望好书大卖!原文提供了样章下载1.1M,pdf格式的。如果大家想下载可以访问源地址:http://bbs.51js.co
- 在此之前,我一直都在研究JavaScript相关的反调试技巧。但是当我在网上搜索相关资料时,我发现网上并没有多少关于这方面的文章,而且就算有
- 项目实现利用face++开发一个课堂签到的软件,实现面向摄像头即可完成记录学号、姓名和时间的签到工作。项目架构项目使用场景代码:流程代码,主
- 一、Matplotlib 绘图在数据分析中,数据可视化也非常重要,通过直观的展示过程、结果数据,可以帮助我们清晰的理解数据,进而更好的进行分
- 我们可以用动态产生变量的方法,从表格里捕捉数据,动态地创造“剥离”变量引号并且“清理”它,见下列代码,我们只需键入变量名称,选择 query
- 详解python里使用正则表达式的分组命名方式分组匹配的模式,可以通过groups()来全部访问匹配的元组,也可以通过group()函数来按
- 树形目录显示程序问题描述:在我们项目中常常会出现自关联的数据表,如果我们从整体看去,整个表就呈现为一个树形数据结构(对于复杂的情况,它可能变
- 有时候需要比较大的计算量,这个时候Python的效率就很让人捉急了,此时可以考虑使用numba 进行加速,效果提升明显~(numba 安装貌
- 循环是我们经常用到的一个概念,比如,循环计算数字叠加、循环输出文字内容等。循环是运行重复内容的一个最简单的方法,简化了代码流程,增加了时效性
- 题目描述原题链接 :35. 搜索插入位置 - 力扣(LeetCode) (leetcode-cn.com)给定一个排序数组和一个目标值,在数
- 2020.3.7准备scrapy,使用anaconda创建一个新的环境,执行“conda create -n scrapyEnv pytho
- 运行结果(2020-2-4日数据)数据来源news.qq.com/zt2020/page/feiyan.htm抓包分析日报数据格式"
- LBound函数:返回指定数组维的最小可用下标;UBound函数:返回指定数组维的最小可用上标;LBound(arrayname, [,di
- 准备工作我准备了两个表格数据,以此展示本期的表格的合并的工作。数据示例如下:表格1表格2接着将这两个表格的数据分别导入python中,导入代
- 年前帮manager 招GUI设计实习生 (PS. 这个实习生职位依然open,欢迎有兴趣的同学来投,邮箱jj.ying [at] hp.c
- 概述OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大. 今天小白就带大家一起携手走进 OpenCV 的世界.梯度运算梯度:
- 这篇文章主要介绍了PYTHON发送邮件YAGMAIL的简单实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- Python实现新版正方系统滑动验证码识别算法和方案步骤一:点击数据分析点击滑动按钮,将发送一个请求到 /zfcaptchaLogin请求内
- 当成功安装了PHP,MYSQL后,我们一般要安装phpMyAdmin来管理你的mysql。本文介绍了phpMyAdmin 2.10.2的配置
- 今天要给大家分享的是一款自己写的屏保程序,大学大家最头疼的就是四六级的考试了,上次考试做阅读的时候,情不自禁的发呆,想着如果我能在电脑上写一