Python Socketserver实现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"}

到这里差不多就没了,

以上是 Python Socketserver实现FTP文件上传下载代码实例 的全部内容, 来源链接: utcz.com/z/318030.html

回到顶部