python第四十一天---作业:简单FTP

时间:2024-01-10 08:38:38

作业要示:

开发简单的FTP:
1. 用户登陆
2. 上传/下载文件
3. 不同用户家目录不同
4. 查看当前目录下文件
5. 充分使用面向对象知识

REDMAE

 用户登陆

 1、查看用户目录文件
2、上传文件,
3、下载方件
4、退出 程序结构:
socket_server_client/#程序目录
|- - -clients/#client程序主目录
| |- - -__init__.py
| |- - -bin/#启用目录
| | |- - - __init__.py
| | |- - -socket_client.py#客户端启动
| |
| |- - -cfg/#配置文件目录
| | |- - - __init__.py
| | |- - -config.py#配置文件
| |
| |- - -core/#主要程序目录
| | |- - - __init__.py
| | |- - -client_func.py#主要函数
| |
| |- - -home/#客户端下载文件目录
|
|- - -servers/#server程序主目录
| |- - -__init__.py
| |- - -bin/#启用目录
| | |- - - __init__.py
| | |- - -registration.py#用户注册
| | |- - -socket_server.py#服务端启动 | |
| |- - -cfg/#配置文件目录
| | |- - - __init__.py
| | |- - -config.py#配置文件
| |
| |- - -core/#主要程序目录
| | |- - - __init__.py
| | |- - -server_classc.py#主要函数
| |
| |- - -db/#用户上传文件主目录
| |- - -user_file/#用户上传目录
| |- - -user_names#注册用户文件
|

服务端

servers/

    bin/

registration.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan
import socket,os,json,sys,pickle BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量
sys.path.append(BASE_DIR)#增加环境变量
from cfg import config
print('用户注册'.center(60,'='))
while True:
user_=input('请输入您要注册的用户名:').strip()
user_dir=os.path.join(config.USER_DIR,user_)#拼接用户目录路径
if os.path.isdir(user_dir):# 判断一个目录是否存在
print('用户已经存在请重输!')
continue
else:
pwd_=input('请输入密码:').strip()
pwd_two=input('请确认密码:').strip()
if pwd_==pwd_two:
try:
os.mkdir(user_dir)#创建目录
except Exception as e:
print(e)
continue
finally:
file_dir=user_dir+'\\user'#用户目录下的用户名文件
if not os.path.isfile(config.USER_FILE):
with open(config.USER_FILE,'w',encoding='utf-8') as f:
f.write('{}')
with open(config.USER_FILE,'r+',encoding='utf-8') as f:
data=eval(f.readline())
data[user_]=pwd_
f.seek(0)
f.write(str(data))
print('用户[%s]注册成功!'%user_)
exit()

socket_server.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan
import socket,os,json
import sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量
sys.path.append(BASE_DIR)#增加环境变量 from core.server_class import listen_func
s=socket.socket()#定义
s.bind(('localhost',9000))#绑定要监听的 端口
s.listen(5)#对列5
print('正在监听中')
listen_func(s)

cfg/

config.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan
import os ,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量
sys.path.append(BASE_DIR)#增加环境变量 USER_DIR=BASE_DIR+'\db\\user_file\\'#定义用户目录文件路径变量 USER_FILE=BASE_DIR+'\db\\user_names'#定义用户文件路径变量

core/

server_class.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan
import socket,os,json,sys,pickle BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量
sys.path.append(BASE_DIR)#增加环境变量 from cfg import config #用户名检测函数
def open_file_list(name,pas):#传入当前类
with open(config.USER_FILE,'r',encoding='utf-8') as f:
data=eval(f.readline())
if name in data and pas==data[name]:
return True
else:
return False #连接类
class socket_server(object):
'''连接类'''
file_path=config.USER_DIR#用户路经变量
def __init__(self,data,conn):#传入用户名,密码
self.DATA=data
self.conn=conn def show_process(self,lens):
received_size=0#定义大小
current_percent=0#当前大小百分比
while received_size<lens:
if int((received_size/lens)*100)>current_percent:
print('#',end='',flush=True)
current_percent=int((received_size/lens)*100)
new_size=yield
received_size+=new_size def ret_l(self):
ret=socket_server.login(self.DATA["name"],self.DATA['pwd'],self.conn)#用户名检测
return ret
def open_f(self,ret):#打开目录
file_dir=os.path.join(socket_server.file_path,ret['data']['user'])#用户目录
file_name=os.listdir(file_dir)#目录文件列表
f=file_dir+self.DATA['filename']##上传的文件名
return file_dir,file_name,f#返回 def ls_file(self,data):#查看文件
self.conn.send(json.dumps(data[1]).encode()) def send_file(self,data): if self.DATA['filename'] in data[1]:
f=data[0]+'/'+self.DATA['filename']
file_obj=open(f,"rb")#打开文件
name=file_obj.name.split('/')[-1]#文件名
sez=os.path.getsize(f)#获取文件大小
print(sez)
data_header={
"action":"put",
"filename":name,
"size":sez
}
self.conn.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息
for line in file_obj:
self.conn.send(line)#发送数据 elif self.DATA['filename'].isdigit():
num=int(self.DATA['filename'])#转为数字
try:
f=data[0]+'/'+data[1][num]#
file_obj=open(f,"rb")#打开文件
name=file_obj.name.split('/')[-1]#文件名
sez=os.path.getsize(f)#获取文件大小
print(sez)
data_header={
"action":"put",
"filename":name,
"size":sez
}
self.conn.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息
for line in file_obj:
self.conn.send(line)#发送数据
self.conn.send(json.dumps(f).encode())#发送文件
except Exception as e:
data={'filename':False}
self.conn.send(json.dumps(data).encode())
else:
data={'filename':False}
self.conn.send(json.dumps(data).encode())
def put_file(self,data):#上传文件
file_obj=open(data[2],'wb')#打开新建 这个文件
rece_size=0#定义 文件大小值
#prten=socket_server.show_process(self.DATA["size"])
#prten.__next__()
while rece_size<self.DATA["size"]:#小于接收的文件大小时,
recv_data=self.conn.recv(4096)
file_obj.write(recv_data)#写入文件
rece_size+=len(recv_data)#增加文件大小计算 else:
print("文件[%s]接收完毕!"%self.DATA["filename"])
file_obj.flush()
file_obj.close()#关闭文件 @staticmethod
def login(name,pas,conn):#用户检测 函数
try:
if open_file_list(name,pas):
tag=True
error=''
datas={'user':name}
data={'mag':'用户认证通过','tag':True}
print(json.dumps(data).encode())
conn.send(json.dumps(data).encode())
else:
raise Exception('\033[41;1m用户名或密码错误\033[0m' %name)
except Exception as e:
tag=False
error=str(e)
datas=''
data={'mag':'用户或密码错误','tag':False}
print('发送数据%s'%data)
conn.send(json.dumps(data).encode())
return {'tag':tag,'error':error,'data':datas} #监听函数
def listen_func(s):
while True:
conn,client_addr=s.accept()#端口监听中....返回两个值 ,联接编号对象 , ip
print('获取到新连接:',client_addr)
while True:
data=conn.recv(4096)#接收数据 指令
print('接收的数据:',data)
data= json.loads(data.decode())#反序列
if len(data)==0:
break
if data['action']=='user':#如果是用户名,进行认证\
serv=socket_server(data,conn)
ret=serv.ret_l()
if ret['tag']:
pass
else:
continue print(data)
if data['action']=="put":#如果接收的字典中是put,就是进行接收
serv=socket_server(data,conn)
serv.put_file(serv.open_f(ret))#调对象方法
elif data['action']=='get':#下载
serv=socket_server(data,conn)#实例化
serv.send_file(serv.open_f(ret))#调 用方法
elif data['action']=='ls':#查看
serv=socket_server(data,conn)
serv.ls_file(serv.open_f(ret))
continue

客户端

clients/

bin/

socket_client.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan import socket,os,json,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量
sys.path.append(BASE_DIR)#增加环境变量
from core.client_func import user_pwd
#from core.client_func import show_process
from cfg import config #进度条
def show_process(lens):
received_size=0#定义大小
current_percent=0#当前大小百分比
while received_size<lens:
if int((received_size/lens)*100)>current_percent:
print('#',end='',flush=True)
current_percent=int((received_size/lens)*100)
new_size=yield
received_size+=new_size client=socket.socket()
client.connect(('localhost',9000))
while True:
data_d=user_pwd(client)
if data_d['tag']:#运行#用户名登陆成功
while True:
print('''=====指令提示====
查看目录文件: ls
下载文件: get 文件名 或 文件编号 如: get test.txt 或 get 1
上传方件: put 路径/文件名 如 put e:/test.txt
退出:exit
''')
cho=input('指令 >>:').strip()
if len(cho)==0:continue
if cho=='exit':exit()#退出指令
cmd_list=cho.split()
if cmd_list[0]=='put':#如果等于下载指令
if len(cmd_list)==1:
print('没有输入相关文件名')
continue
filename=cmd_list[1]
if os.path.isfile(filename):#如果文件存在
file_obj=open(filename,"rb")#打开文件
name=file_obj.name.split('/')[-1]#文件名
#name=filename.split("\\")[-1]#文件名
sez=os.path.getsize(filename)#获取文件大小
data_header={
"action":"put",
"filename":name,
"size":sez
}
client.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息 print("文件[%s]发送中...."%data_header["filename"])
for line in file_obj:
client.send(line)
else:
print("文件[%s]发送完毕!"%data_header["filename"])
else:
print('该文件不存在')
continue
elif cmd_list[0]=='get':#如查等 于上传指令
if len(cmd_list)==1:
print('没有输入相关文件名')
continue
filename=cmd_list[1]
print(filename)
data_header={
"action":"get",
"filename":filename,
"size":''
}
client.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息
datas=client.recv(4096)#接收数据 指令
data_l= json.loads(datas.decode())#反序列
if not data_l['filename']:
print('文件不存在')
continue
file_dir=config.USER_DIR+data_l["filename"]
file_obj=open(file_dir,'wb')#打开新建 这个文件
rece_size=0#定义 文件大小值
prten=show_process(data_l["size"])
prten.__next__()
while rece_size<data_l["size"]:#小于接收的文件大小时,
recv_data=client.recv(4096)
file_obj.write(recv_data)#写入文件
rece_size+=len(recv_data)#增加文件大小计算
try:
prten.send(len(recv_data))
except StopIteration as e:
print('100%') else:
print("文件[%s]接收完毕!"%data_l["filename"])
file_obj.flush()
file_obj.close()#关闭文件
elif cmd_list[0]=='ls':#查看目录文件
data_header={
"action":"ls",
"filename":'',
"size":''
}
client.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息
datas=client.recv(4096)#接收数据 指令
data_l= json.loads(datas.decode())#反序列
for k,v in enumerate(data_l):
print('编号: %s 文件名:%s'%(k,v)) else:
print(data_d['mag'])

cfg/

config.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan import os ,sys
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#获取相对路径转为绝对路径赋于变量
sys.path.append(BASE_DIR)#增加环境变量 USER_DIR=BASE_DIR+'\home\\'#定义用户目录文件路径变量

core/

client_func.py

 #!usr/bin/env python
#-*-coding:utf-8-*-
# Author calmyan
import socket,os,json,sys
#用户名登陆函数
def user_pwd(client):
user_=input('请输入用户名:').strip()
pwd_=input('请输入密码:').strip()
data_header={
"action":"user",
"name":user_,
"pwd":pwd_
}
client.send(json.dumps(data_header).encode())#用json 序列化后,发送相关 信息
data=client.recv(4096)#接收数据 指令
data_s=json.loads(data.decode('utf-8'))#反序列
return data_s #进度条
def show_process(lens):
received_size=0#定义大小
current_percent=0#当前大小百分比
while received_size<lens:
if int((received_size/lens)*100)>current_percent:
print('#',end='',flush=True)
current_percent=int((received_size/lens)*100)
new_size=yield
received_size+=new_size