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 ...
随机推荐
- python pip安装找不到指定包的时候怎么解决
在该网址上下载对应版本的包然后安装即可. https://www.lfd.uci.edu/~gohlke/pythonlibs/
- WGS84,GCJ02, BD09坐标转换
public class Gps { private double wgLat; private double wgLon; public Gps(double wgLat, double wgLon ...
- CentOS7 搭建影梭服务器
安装Python包管理工具 yum install python-setuptools && easy_install pip 安装Shadowsocks pip install sh ...
- Linux 学习 (一) Linux简介
Linux达人养成计划 I 学习笔记 Linux 内核官网:www.kernel.org 内核版本说明:主版本.次版本.末版本,如2.6.18 Linux 主要发行版本 RedHat: 服务器领域,部 ...
- Linux压缩和解压命令
zip命令: 压缩 :zip -r files.zip fileFolder 解压:unzip files.zip tar命令: 压缩:tar -cvf files.tar fileFolder 解压 ...
- js 异步代码
这段时间一直在用node.js做毕设的后台,所以需要一些异步代码操作,主要的异步方式有:Promise.Generator 和 async / await,但下面主要讲 Promise 和 async ...
- Java启动命令与Maven打包设置
一.Java启动命令 java程序的启动方式有三种: 1.java -jar 生成的jar包中,manifest文件定义了Main Class,可使用该命令 java -jar test.jar 2. ...
- java代码自动下载Spring Boot用户手册
本示例演示Spring Boot 1.5.9.RELEASE版本的用户手册下载 pom.xml <?xml version="1.0" encoding="UTF- ...
- Codeforces Round #437 Div. 1
A:显然构造一组只包含1和2面值的数据即可. #include<iostream> #include<cstdio> #include<cmath> #includ ...
- xml 模块
XML ———可扩展的标记语言 也是一种通用的数据格式 之所以用它 也是因为跨平台 XML 的语法格式: 1,任何的起始标签都必须有一个结束标签. <> 起始标签 </>结束标 ...