fftp_client.py
import optparse
import socket
import json
import os
import sys
STATUS_CODE = {
250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
251 : "Invalid cmd ",
252 : "Invalid auth data",
253 : "Wrong username or password",
254 : "Passed authentication",
255 : "Filename doesn't provided",
256 : "File doesn't exist on server",
257 : "ready to send file",
258 : "md5 verification",
800 : "the file exist,but not enough ,is continue? ",
801 : "the file exist !",
802 : " ready to receive datas",
900 : "md5 valdate success"
}
class ClientHandler():
def __init__(self):
self.op = optparse.OptionParser()
self.op.add_option('-s','--server',dest='server')
self.op.add_option('-P','--p',dest='port')
self.op.add_option('-u', '--username', dest='username')
self.op.add_option('-p', '--password', dest='password')
self.options,self.args = self.op.parse_args()
#对端口和ip地址进行安全校验
self.verify_args(self.options,self.args)
#连接服务端
self.make_connection()
self.mainPath = os.path.dirname(os.path.abspath(__file__))
self.last=0
def verify_args(self,options,args):
server = options.server
port=options.port
# username=options.username
# password=options.password
if int(port)>0 and int(port)<65535:
return True
else:
exit('the port is in 0-65535')
def make_connection(self):
self.sock=socket.socket()
self.sock.connect((self.options.server,int(self.options.port)))
#和服务端进行交互
def interactive(self):
if self.authenticate():
print('begin to interactive........')
cmd_info = input('[%s]'%self.current_dir).strip()#put 12png images
cmd_list = cmd_info.split()
if hasattr(self,cmd_list[0]):
func=getattr(self,cmd_list[0])
func(*cmd_list)
else:
print("Invalid cmd")
#上传文件
def put(self,*cmd_list):
#put 12.png images
action,local_path,target_path=cmd_list
local_path=os.path.join(self.mainPath,local_path)
file_name = os.path.basename(local_path)
file_size=os.stat(local_path).st_size
data={
'action':'put',
'file_name':file_name,
'target_path':target_path
}
self.sock.send(json.dumps(data).encode('utf8'))
is_exist=self.sock.recv(1024).decode('utf8')
has_sent=0
if is_exist=='800':
#文件不完整
choice=input('is continue?[Y/N]').strip()
if choice.upper()=='Y':
self.sock.sendall('Y'.encode('utf8'))
continue_position=self.sock.recv(1024).decode('utf8')
has_sent+=int(continue_position)
else:
self.sock.sendall('N'.encode('utf8'))
elif is_exist=='801':
#文件完全存在
return
f=open(local_path,'rb')
f.seek(has_sent)
while has_sent<file_size:
data=f.read(1024)
self.sock.sendall(data)
has_sent+=len(data)
#进度条。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
self.show_progress(has_sent,file_size)
f.close()
print('put success!')
#进度条
def show_progress(self,has,total):
rate=float(has)/float(total)
rate_num=int(rate*100)
if self.last!=rate_num:
sys.stdout.write('%s%% %s\r'%(rate_num,"#"*rate_num))
self.last=rate_num
#查看文件下的目录
def ls(self,*cmd_list):
data={
'action':'ls',
}
self.sock.sendall(json.dumps(data).encode('utf8'))
data = self.sock.recv(1024).decode('utf8')
print(data)
def cd(self,*cmd_list):
#cd images
data={
'action':'cd',
'dirname':cmd_list[1]
}
self.sock.sendall(json.dumps(data).encode('utf8'))
data = self.sock.recv(1024).decode('utf8')
self.current_dir=os.path.basename(data)
#创建文件夹
def mkdir(self,*cmd_list):
data={
'action':'mkdir',
'dirname':cmd_list[1]
}
self.sock.sendall(json.dumps(data).encode('utf8'))
data = self.sock.recv(1024).decode('utf8')
def authenticate(self):
if self.options.username is None or self.options.password is None:
username = input('username:')
password = input('password:')
return self.getauth_result(username,password)
return self.getauth_result(self.options.username,self.options.password)
def respones(self):
data = self.sock.recv(1024).decode('utf8')
data = json.loads(data)
return data
def getauth_result(self,user,pwd):
data = {
'action':'auth',
'username':user,
'password':pwd
}
self.sock.send(json.dumps(data).encode('utf8'))
response=self.respones()
print('response:',response['state_code'])
if response['state_code']==254:
self.user = user
self.current_dir=user
print(STATUS_CODE[254])
return True
else:
print(STATUS_CODE[response['state_code']])
ch = ClientHandler()
#交互
ch.interactive()
复制代码
server.py
import configparser
import socketserver
import json
from conf import settings
import os
STATUS_CODE = {
250 : "Invalid cmd format, e.g: {'action':'get','filename':'test.py','size':344}",
251 : "Invalid cmd ",
252 : "Invalid auth data",
253 : "Wrong username or password",
254 : "Passed authentication",
255 : "Filename doesn't provided",
256 : "File doesn't exist on server",
257 : "ready to send file",
258 : "md5 verification",
800 : "the file exist,but not enough ,is continue? ",
801 : "the file exist !",
802 : " ready to receive datas",
900 : "md5 valdate success"
}
class ServerHandle(socketserver.BaseRequestHandler):
def handle(self):
while 1 :
data = self.request.recv(1024).strip()
data = json.loads(data.decode('utf8'))
if data.get('action'):
if hasattr(self,data.get('action')):
func = getattr(self,data.get('action'))
func(**data)
else:
print('error')
else:
print('error')
def send_response(self,state_code):
response={'state_code':state_code,}
self.request.sendall(json.dumps(response).encode('utf8'))
def auth(self,**data):
username=data['username']
password=data['password']
user = self.authenticate(username,password)
if user :
self.send_response(254)
else:
self.send_response(253)
def authenticate(self,user,pwd):
cfg=configparser.ConfigParser()
cfg.read(settings.ACCOUNT_PATH)
if user in cfg.sections():
if cfg[user]['Password']==pwd:
self.user = user
self.mainPath=os.path.join(settings.BASE_DIR,'home',self.user)
print('登录成功!')
return user
#上传文件
def put(self,**data):
print('data',data)
file_name=data.get('file_name')
file_size=data.get('file_size')
target_path=data.get('target_path')
abs_path=os.path.join(self.mainPath,target_path,file_name)
#####################
has_received=0
#如果路径下已经存在这个文件
if os.path.exists(abs_path):
file_has_size=os.stat(abs_path).st_size
if file_has_size<file_size:
#断点续传
self.request.sendall('800'.encode('utf8'))
choice=self.request.recv(1024).decode('utf8')
if choice=='Y':
self.request.sendall(str(file_has_size).encode('utf8'))
has_received=file_has_size
f=open(abs_path,'ab')
else:
f=open(abs_path,'wb')
else:
#完整
self.request.sendall('801'.encode('utf8'))
return
else:
self.request.sendall('802'.encode('utf8'))
f = open(abs_path, 'wb')
while has_received<file_size:
try:
data = self.request.recv(1024)
except Exception as e:
break
f.write(data)
has_received+=len(data)
f.close()
#查看文件下的目录
def ls(self,**data):
file_list=os.listdir(self.mainPath)
file_str = '\n'.join(file_list)
if not len(file_list):
file_str='<empty dir>'
self.request.sendall(file_str.encode('utf8'))
#切换目录
def cd(self,**data):
dirname=data.get('dirname')
if dirname=='..':
self.mainPath=os.path.dirname(self.mainPath)
else:
self.mainPath=os.path.join(self.mainPath,dirname)
self.request.sendall(self.mainPath.encode('utf8'))
#创建文件夹
def mkdir(self,**data):
dirname=data.get('dirname')
path=os.path.join(self.mainPath,dirname)
if not os.path.exists(path):
if '/' in dirname:
os.makedirs(path)
else:
os.mkdir(path)
self.request.sendall('create success'.encode('utf8'))
else:
self.request.sendall('dirname exist'.encode('utf8'))
复制代码
setting.py
import os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
IP='127.0.0.1'
PORT=8080
ACCOUNT_PATH=os.path.join(BASE_DIR,'conf','accounts.cfg')
复制代码
ftp_server.py
import os,sys
PATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PATH)
# print(PATH)
# print(sys.path)
# print(os.path.dirname(os.path.abspath(__file__)))
# print(os.path.abspath(__file__))
from core import main
if __name__ == '__main__':
main.ArgvHandler()
复制代码