基於Python3編寫, 實現文件上傳下載, 支持多個客戶端TCP方式連接服務端, 命令行操作
預覽圖:
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()
有錯誤或者疑問請指出謝謝!