编写ftp客户端程序:
import socket, os, json
class my_ftp_client(object):
def __init__(self):
self.client = socket.socket()
def help(self):
msg = '''
get filename
put filename
'''
def connect(self, ip, port): # 与服务器端建立连接,ip代表服务器端的ip地址,port代表服务器端的端口
self.client.connect((ip, port))
def interaction(self): # 让用户输入执行,然后调用对应的函数来与服务器端进行交互
while True:
data = input("<<").strip() # 用户输入指令
if len(data) == 0: # 如果指令输入有误,重新输入
continue
data_one = data.split()[0] # 得到用户输入的操作,如果用户如果输入'put filename'(往服务器端传文件名为filename的文件),那么data_one就是'put'
if hasattr(self, "cmd_%s" % data_one): # 如果我们写的这个类中有名为'cmd_put'的函数,就执行下面的代码
func = getattr(self, "cmd_%s" % data_one) # func实际上就是'cmd_put'
func(data) # 调用类中名为'cmd_put'的函数
else:
self.help()
def cmd_put(self, *args):
data_split = args[0].split() # 得到用户输入的指令
if len(data_split) > 1: # 确保指令是正确的
filename = data_split[1] # 得到文件名
if os.path.isfile(filename): # 这是个文件
filesize = os.stat(filename).st_size
msg = { # 定义一个json文本,里面存储的是文件的一些信息
'action': 'put', # 文件对客户端的操作
'filename': filename, # 文件名
'filesize': filesize, # 文件大小
}
self.client.send(json.dumps(msg).encode()) # 将文件的信息一次性传给服务器端,这个地方dump是将json文本类型转化为其他存储格式
print('等待服务器端返回确认指令!')
server_response = self.client.recv(1024) # 接收服务器端发送来的确认指令
f = open(filename, 'rb')
for line in f: # 遍历文件,将文件内容传送给服务器端
self.client.send(line)
else:
print("file end!")
else: # 指令是错误的
print("instruction error!")
def cmd_get(self, *args): # 这个函数是从客户端得到名为filename的文件
data_split = args[0].split() # 得到用户输入的指令
if len(data_split) > 1: # 指令正确,执行下面的操作
file_name = data_split[1] # 得到文件名
msg = { # 定义一个json文本,里面存储的是文件的一些信息
'action': 'get', # 文件对客户端的操作
'filename': file_name, # 文件名
}
self.client.send(json.dumps(msg).encode()) # 给服务器端发送这个文件的信息
print('等待服务器端返回确认指令!')
recevice_data = self.client.recv(1024).strip() # 接收服务器端发送回来的指令
data_json = json.loads(recevice_data.decode()) # 将recevice_data解析出来
One_data = data_json["instruction"] # 得到服务器端发回来的第一个信息
if One_data == 'Not Find': # 如果第一个信息为'Not Find',说明服务器端没有名为file_name的文件
return
else: # 否则,有名为file_name的文件
file_size = data_json["file_size"] # 得到这个文件的大小
now_size = 0 # 当前接收到的文件的大小
f = open(file_name, 'wb')
while now_size < file_size: # 开始接收文件
data = self.client.recv(1024)
f.write(data)
now_size += len(data)
else:
print("文件接收完毕!")
ftp = my_ftp_client()
ftp.connect('127.0.0.1', 8000)
ftp.interaction()
编写ftp服务端程序:
import os
import socketserver
import json
class MyTCPHandler(socketserver.BaseRequestHandler):
def put(self, *args):
data_json = args[0] # 得到json文本
fullname = data_json['filename'] # 得到文件名
"""
提供上传文件和文件夹的功能:
(1)上传文件,接受的信息为:111.txt
(2)上传文件夹,接受的信息为(文件夹名为:111):111
"""
file_path = os.path.join(os.getcwd(), os.path.split(os.path.split(fullname)[0])[-1])
if not os.path.exists(file_path):
os.makedirs(file_path)
filename = os.path.join(file_path, os.path.split(fullname)[-1])
filesize = data_json['filesize'] # 得到文件的大小
now_size = 0 # 这是服务器端已经接收到的文件的大小
if os.path.isfile(filename): # 如果服务器端已经存在名为filename的文件,就新建一个名为'filename.new'的文件
f = open(filename + '.new', 'wb')
else: # 否则,就建出名为filename的文件
f = open(filename, 'wb')
self.request.send(b'200 ojbk') # 给客户端返回服务器端已经准备好接受文件的信息
while now_size < filesize: # 开始接收文件
data = self.request.recv(1024)
f.write(data) # 将接收到的文件的内容写入到服务器端中的名为filename的文件中去
now_size += len(data) # now_size加
else:
print("file recv over!") # 文件接收完毕
def get(self, *args):
data_json = args[0] # 得到客户端发送来的信息
file_name = data_json['filename'] # 得到客户端想要从服务器端获取的文件的文件名
if os.path.isfile(file_name): # 服务器端有这个文件
filesize = os.stat(file_name).st_size # 得到这个文件的大小
xiao_name = os.path.split(file_name)[-1]
msg = { # 将这个文件的信息传给服务器端
"instruction": 'Find the file', # 这个信息说明服务器端已经找到了这个文件了
"file_size": filesize, # 返回给客户端这个文件的大小
}
self.request.send(json.dumps(msg).encode())
f = open(file_name, 'rb') # 打开这个文件
for line in f: # 给客户端发送文件内容
self.request.send(line)
else:
print("文件传输完毕!")
else: # 服务器端没有这个文件
msg = {
"instruction": 'Not Find', # 这个信息说明服务器端没有找到这个文件
'file_size': 0 # 文件大小为0
}
self.request.send(json.dumps(msg).encode())
def handle(self):
while True:
try:
self.data = self.request.recv(1024).strip()
print("{} wrote".format(self.client_address[0])) # 打印客户端的ip地址
print("data:", self.data)
data_json = json.loads(self.data.decode())
action = data_json['action'] # 得到要执行的操作
if hasattr(self, action): # 这个类中有名为action的函数
func = getattr(self, action) # func就相当于是'action'
func(data_json)
except ConnectionResetError as e: # 捕捉到错误了
print("error:", e)
break
HOST, PORT = "127.0.0.1", 8000 # 填写服务器的ip,端口
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) # 实例化ThreadingTCPServer,并传递(端口号+IP),和请求类名
server.serve_forever() # 关闭
分别运行客户端和服务端的程序,在客户端输入:put 文件夹名/文件名可以将文件上传到服务端,在客户端输入:get 文件名可以将文件从服务端下载到客户端,以上就是ftp实现文件上传和下载的基本方法,各位读者有疑问的可以私信博主或评论留下足迹。