该项目已图形界面化后作为一个小功能加入我的另一个项目中
感兴趣的朋友可以看看: 使用Python3编写一个聊天室
预览图:
download为客户端保存文件目录, resources为服务端保存文件目录
代码分为服务端和客户端两部分, 实现如下:
FileServer.py
#!/usr/bin/python3
# -*- coding:utf-8 -*-
import socket
import threading
import time
import os
import os.path
import json #用于将列表或字典转换成json字符串传输
first = r'./resources'
os.chdir(first) # 把first设为当前工作路径
IP = ''
PORT = 50008
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.bind( (IP, PORT) )
s.listen(3)
def tcp_connect(conn, addr):
print('Connected by: ', addr)
while True:
data = conn.recv(1024)
data = data.decode()
print('Received message from {0}: {1}'.format(addr, data))
if data == 'quit':
print('Disconnected from {0}'.format(addr))
break
order = data.split()[0] # 获取动作
recv_func(order, data)
conn.close()
# 传输当前目录列表
def sendList():
listdir = os.listdir(os.getcwd())
listdir = json.dumps(listdir)
conn.sendall(listdir.encode())
# 发送文件函数
def sendFile(message):
name = message.split()[1] #获取第二个参数(文件名)
# 如果没有指定下载的文件则给客户端返回False
if name in os.listdir() and '.' in name:
conn.send('ok!'.encode())
fileName = r'./' + name
with open(fileName, 'rb') as f:
while True:
a = f.read(1024)
if not a:
break
conn.send(a)
time.sleep(0.1) # 延时确保文件发送完整
conn.send('EOF'.encode())
print('文件发送完成!')
else:
conn.send('False'.encode())
# 保存上传的文件到当前工作目录
def recvFile(message):
name = message.split()[1] #获取文件名
fileName = r'./' + name
print('开始保存!')
with open(fileName, 'wb') as f:
while True:
data = conn.recv(1024)
if data == 'EOF'.encode():
print('保存成功!')
break
f.write(data)
# 发送当前工作目录
def pwd():
path = os.getcwd()
conn.send(path.encode())
# 切换工作目录
def cd(message):
message = message.split()[1] # 截取目录名
# 如果目录不存在或不是..则报错
if not message in os.listdir():
if message != '..':
conn.send('False2'.encode())
return
if '.' in message:
if message != '..':
conn.send('False1'.encode())
return
f = r'./' + message
os.chdir(f)
pwd()
# 判断输入的命令并执行对应的函数
def recv_func(order, message):
if order == 'get':
return sendFile(message)
elif order == 'put':
return recvFile(message)
elif order == 'dir':
return sendList()
elif order == 'pwd':
return pwd()
elif order == 'cd':
return cd(message)
print('tcp server is running...')
while True:
conn, addr = s.accept()
t = threading.Thread(target=tcp_connect, args=(conn, addr))
t.start()
s.close()
FileClient.py
#!/usr/bin/python3
# -*- coding:utf-8 -*-
'''
登录名: ftp 密码: 空
服务端起始工作目录为resource文件夹
get 文件名:下载文件到download文件夹, 如果文件已存在, 可选择是否覆盖
put 文件名: 上传客户端所在的指定文件到服务端工作目录下
cd 目录名 or ..: 进入或返回上一文件夹
dir: 显示当前目录所有文件和目录名
help: 可用命令 quit: 断开连接 cls: 清屏
'''
import socket
import threading
import time
import os
import json #用于将列表或字典转换成json字符串传输
IP = '127.0.0.1'
PORT = 50008
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.connect((IP, PORT))
def main():
user = input('user: ')
pwd = input('password: ')
if pwd == '' and user == 'ftp':
while True:
message = input('>>> ')
if message == '':
continue
if message == 'quit':
s.send(message.encode())
break
enter = message.split()[0] # 获取命令的第一个参数(动作)
ent_func(enter, message)
else:
input('用户名或密码错误!')
main()
s.close()
# 输入help或命令有误时显示(help)
def helpList():
print('''
get: 下载\tput: 上传\thelp: 可用命令
quit: 断开连接\tcd: 进入文件夹\tdir: 当前目录
cls: 清屏''')
# 接收下载文件(get)
def get(message):
name = message.split()
if len(name) != 2:
return print('请输入文件名')
name = name[1] # 获取命令的第二个参数(文件名)
# 判断是否已下载该文件
if name in os.listdir(r'./download'):
while True:
ch = input('文件已存在是否覆盖[Y/N]:')
if ch == 'Y' or ch == 'y':
break
elif ch == 'N' or ch == 'n':
print('取消下载')
return
else:
continue
# 判断服务端是否有指定下载的文件, 没有则报错
s.send(message.encode())
data = s.recv(1024)
if data.decode() == 'False':
print('没有该文件')
return
fileName = r'./download/' + name
print('开始下载文件!')
with open(fileName, 'wb') as f:
while True:
data = s.recv(1024)
if data == 'EOF'.encode():
print('下载完成!')
break
f.write(data)
# 上传客户端所在文件夹中指定的文件到服务端
def put(message):
name = message.split()
if len(name) != 2:
return print('请输入文件名')
name = name[1] # 获取文件名
# 判断 Upload 目录中是否有该文件
if not name in os.listdir():
print('没有该文件')
return
if '.' not in name:
print('请输入正确的文件名!')
return
s.send(message.encode())
fileName = r'./' + name
print('开始上传文件!')
with open(fileName, 'rb') as f:
while True:
a = f.read(1024)
if not a:
break
s.send(a)
time.sleep(0.1) # 延时确保文件发送完整
s.send('EOF'.encode())
print('文件上传成功')
# 将接收到的目录文件列表打印出来(dir)
def recvList(enter):
s.send(enter.encode())
data = s.recv(1024)
data = json.loads(data.decode())
for i in range(len(data)):
print(data[i-1])
# 打印服务端当前工作目录(pwd)
def pwd(enter):
s.send(enter.encode())
data = s.recv(1024)
print(data.decode())
# 进入指定目录(cd)
def cd(enter, message):
s.send(message.encode())
data = s.recv(1024).decode()
if data == 'False1':
print('请输入正确的目录名')
return
if data == 'False2':
print('没有该目录!')
return
print(data)
# 清屏, 命令行下有效(cls)
def cls():
os.system('cls')
# 判断输入的命令并执行对应的函数
def ent_func(enter, message):
if enter == 'help':
return helpList()
elif enter == 'get':
return get(message)
elif enter == 'put':
return put(message)
elif enter == 'dir':
return recvList(enter)
elif enter == 'pwd':
return pwd(enter)
elif enter == 'cd':
return cd(enter, message)
elif enter == 'cls':
return cls()
else:
print('无效命令')
main()
有错误或者疑问请指出谢谢!