python基础之FTP
目的:实现客户端到服务器的上传功能
所需文件夹:
客户端是FTP_client 服务端是FTP_server
bin文件存放执行文件,conf下存放配置文件,core下是核心文件,home是家目录,logger存放日志文件.
客户端代码 ftp_client.py:
import optparse
import socket
import os,sys
import json
import time
import hashlib STATUS_CODE = {
250: "Invalid cmd format,e.g:{'action':'get','filname':'test.py','size':344}",
251: "Incalid cmd",
252: "Invalid auth data",
253: "Wrong username or password",
254: "Passed authentication",
255: "Filename doesn't provided",
256: "Filename doesn't exist on the 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 validate success"
} class ClientHandler():
def __init__(self):
self.op = optparse.OptionParser()
self.op.add_option("-s","--server",dest="server")
self.op.add_option("-P","--port",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()
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):
print("Begin to interactive...")
if self.authenticate():
while True:
cmd_info = input("[%s]"%self.current_dir).strip()
cmd_list = cmd_info.split()
if hasattr(self,cmd_list[0]):
func = getattr(self,cmd_list[0])
func(*cmd_list) def put(self,*cmd_list):
# put 12.jpg 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,
"file_size": file_size,
"target_path": target_path
} self.sock.send(json.dumps(data).encode('utf-8')) is_exist = self.sock.recv(1024).decode('utf-8')
######################
has_sent = 0
if is_exist=="":
#文件完整
choice = input("The file exist,but not enough,is continue?[Y/N]").strip()
if choice.upper()=='Y':
self.sock.sendall("Y".encode('utf-8'))
continue_position = self.sock.recv(1024).decode('utf-8')
has_sent+=int(continue_position) else:
self.sock.sendall("N".encode('utf-8')) elif is_exist=="":
#文件完全存在
print('The file exist')
return f = open(local_path,"rb")
f.seek(has_sent)
start = time.time()
md5_obj = hashlib.md5()
while has_sent<file_size:
data = f.read(1024)
self.sock.sendall(data)
has_sent+=len(data)
md5_obj.update(data)
self.show_process(has_sent,file_size)
else:
print("post success!!!")
md5_val = md5_obj.hexdigest()
md5_server = self.sock.recv(1024).decode('utf-8')
print(md5_server)
self.sock.sendall(md5_val.encode('utf-8')) f.close()
print("Put Success") def show_process(self,has,total):
rate = float(has)/float(total)
rate_num = int(rate*100)
rate_num_1 = int(rate_num/2)
if self.last!=rate_num:
sys.stdout.write("%s%% %s\r"%(rate_num,"#"*rate_num_1))
self.last = rate_num def authenticate(self):
if self.options.username is None or self.options.password is None:
username = input('username: ')
password = input('password: ')
return self.get_auth_result(username,password) return self.get_auth_result(self.options.username,self.options.password) def response(self):
data = self.sock.recv(1024).decode('utf-8')
data = json.loads(data)
return data def get_auth_result(self,user,pwd):
data = {
"action": "auth",
"username": user,
"password": pwd
}
self.sock.send(json.dumps(data).encode('utf-8'))
response = self.response()
print(response)
if response["status_code"]==254:
self.user = user
self.current_dir = user
print(STATUS_CODE[254])
return True
else:
print(STATUS_CODE[response["status_code"]]) def ls(self,*cmd_list):
data = {
"action":"ls",
}
self.sock.sendall(json.dumps(data).encode('utf-8'))
data = self.sock.recv(1024).decode('utf-8')
print(data) def cd(self,*cmd_list):
data = {
"action": "cd",
"dirname": cmd_list[1],
}
self.sock.send(json.dumps(data).encode('utf-8')) data = self.sock.recv(1024).decode('utf-8')
self.current_dir = self.user + "\\" +os.path.basename(data) ch = ClientHandler()
ch.interactive()
服务端代码 启动代码ftp_server.py
import os,sys
BaseAddress = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BaseAddress)
from core import main
if __name__ == '__main__':
main.ArgvHandler()
核心代码 main.py
import optparse
import socketserver
from conf import settings
from core import server class ArgvHandler():
def __init__(self):
self.op = optparse.OptionParser()
# self.op.add_option('-s','--server',dest='server')
# self.op.add_option('-P','--port',dest='port')
# self.op.add_option('-s','--s',dest='server') options,args = self.op.parse_args()
self.verify_args(options,args) def verify_args(self,options,args):
cmd = args[0]
if hasattr(self,cmd):
func = getattr(self,cmd)
func() def start(self):
print('the server is working...')
s = socketserver.ThreadingTCPServer((settings.IP,settings.PORT),server.SeverHandler)
s.serve_forever() def help(self):
pass
执行代码
import socketserver
import json
import configparser
from conf import settings
import os
import hashlib STATUS_CODE = {
250: "Invalid cmd format,e.g:{'action':'get','filname':'test.py','size':344}",
251: "Incalid cmd",
252: "Invalid auth data",
253: "Wrong username or password",
254: "Passed authentication",
255: "Filename doesn't provided",
256: "Filename doesn't exist on the 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 validate success"
} class SeverHandler(socketserver.BaseRequestHandler):
def handle(self):
while 1:
data = self.request.recv(1024).strip()
data = json.loads(data.decode('utf-8')) if data.get("action"):
if hasattr(self,data.get("action")):
func = getattr(self,data.get("action"))
func(**data)
else:
print('Invalid cmd') def send_response(self,state_code):
response = {"status_code":state_code,'status_mes':STATUS_CODE[state_code]}
self.request.sendall(json.dumps(response).encode('utf-8')) 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):
config = configparser.ConfigParser()
config.read(settings.ACCOUNT_PATH) if user in config.sections():
print("================================") if config[user]["Password"]==pwd:
self.user = user
self.mainPath = os.path.join(settings.BASE_DIR,"home",self.user) print("passed authentication")
return self.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("".encode('utf-8'))
choice = self.request.recv(1024).decode('utf-8')
if choice=="Y":
self.request.sendall(str(file_has_size).encode('utf-8'))
has_received+=file_has_size
f = open(abs_path,"ab")
else:
f = open(abs_path,'wb') else:
#文件完全存在
self.request.sendall("".encode('utf-8'))
return else:
self.request.sendall("".encode('utf-8'))
f = open(abs_path,"wb") md5_obj = hashlib.md5()
while has_received<file_size:
try:
data = self.request.recv(1024)
md5_obj.update(data)
except Exception as e:
break
f.write(data)
has_received+=len(data)
md5_val = md5_obj.hexdigest()
self.request.sendall(md5_val.encode('utf-8'))
md5_client = self.request.recv(1024)
print(md5_client)
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>"
self.request.sendall(file_str.encode('utf-8')) 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('utf-8'))
到此为止,可以简单的完成上传任务,如果需要添加任务,只需要在ftp_client.py和server.py下面定义新的函数进行交互就可以了。
python基础之FTP的更多相关文章
- Python之路3【第一篇】Python基础
本节内容 Python简介 Python安装 第一个Python程序 编程语言的分类 Python简介 1.Python的由来 python的创始人为吉多·范罗苏姆(Guido van Rossum) ...
- python基础之day1
Python 简介 Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言. Python为我们提供了非常完善的基础代码库,覆盖了 ...
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- Day2 - Python基础2 列表、字典、集合
Python之路,Day2 - Python基础2 本节内容 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一, ...
- python基础——面向对象进阶
python基础--面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 ...
- python基础1之 由来、种类、优缺点、安装环境
python基础1之由来.种类.优缺点.安装环境 一.前世今生 Python的创始人是吉多·范罗苏姆(Guido van Rossum),在1989年开发.今年最新的编程语言排行榜中,python名列 ...
- python基础day1
一.python介绍 1.1简介 Python (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum ...
- web自动化 基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架
基于python+Selenium+PHP+Ftp实现的轻量级web自动化测试框架 by:授客 QQ:1033553122 博客:http://blog.sina.com.cn/ishou ...
- Python基础教程 - Tdcqma
1.1 普通字符串 1.21 错误与异常 1.41 XXXXXX 1.61 XXXXXX 1.81 XXXXXX 1.101 XXXXXX 1.2 转义字符串 1.22 装饰器 1 ...
随机推荐
- 【git】git add 添加错文件 撤销
git add 添加 多余文件 这样的错误是由于, 有的时候 可能 git add . (空格+ 点) 表示当前目录所有文件,不小心就会提交其他文件 git add 如果添加了错误的文件的话 撤销操 ...
- Could not render e, see the console.
错误截图: 解决: 在application.properties中开启swagger swagger2.enable=true
- Partition算法以及其应用详解上(Golang实现)
最近像在看闲书一样在看一本<啊哈!算法> 当时在amazon上面闲逛挑书,看到巨多人推荐这本算法书,说深入浅出简单易懂便买来阅读.实际上作者描述算法的能力的确令人佩服.就当复习常用算法吧. ...
- Mysql Router 的集群
1. c:\mysql-router, c:\mysql-5.7.23, 这两个目录的bin都要加入path 2. c:\mysql-shell,在bin下,有一个 mysqlsh.exe, 双击,打 ...
- 深度学习 weight initialization
转自: https://www.leiphone.com/news/201703/3qMp45aQtbxTdzmK.htmla https://blog.csdn.net/shuzfan/articl ...
- Lodop生成文档式模版
Lodop模版有两种方法,一种是传统的JS语句,可以用JS方法里的eval来执行,一种是文档式模版,是特殊格式的base64码,此篇博文介绍文档式模版的生成方法.两种模版都可以存入一下地方进行调用,比 ...
- MySQL启动错误---发生系统错误/系统找不到指定的文件。
今天启动mysql时,突然报错发生系统错误,系统找不到指定的文件.当时有点懵,安装mysql 之后,一直就没有修改过,怎么会报错呢?上网搜索了一下,重新安装一下mysql服务就可以了,现在也不知道什么 ...
- NoClassDefFoundError与ClassNotFoundException
原文地址: https://blog.csdn.net/jamesjxin/article/details/46606307 怎么解决NoClassDefFoundError错误 NoClassDef ...
- 三:C#对象转换Json时的一些高级(特殊)设置;
导航目录: Newtonsoft.Json 概述 一:Newtonsoft.Json 支持序列化与反序列化的.net 对象类型: 二:C#对象.集合.DataTable与Json内容互转示例: ...
- 洛谷P1216数字三角形题解
题目 这道题是一个典型的DP,可以用倒推,顺推的方法,来解这道题.当然用不同的方法他的循环次序是不一样的,所以我们一定要深刻地理解题目的大意,再采用状态转移方程与边界每次求出最优解,并记录循环一遍后就 ...