1. 程式人生 > >python 單使用者多檔案下載 模擬FTP下載

python 單使用者多檔案下載 模擬FTP下載

#伺服器端
#==========================================================================
import socket
import os


# 建立傳輸任務
def read_send_task(file_path, service_client_scoket):
# 二進位制方式開啟原始檔
with open(file_path, 'rb') as file:
while True:
file_data = file.read(1024)
print("正在讀取檔案...")
if file_data:
print("正在傳送資料...")
service_client_scoket.send(file_data)
else:
service_client_socket.send(b"trans_end")
print("讀取檔案併發送資料完成!")
break


def send_task(service_client_socket, share_dir):
# 接收客戶端請求的檔名列表
file_name_list = service_client_socket.recv(1024).decode('gbk').split(",")
print("客戶端請求的檔案列表", file_name_list)
for file_name in file_name_list:
print("準備傳送檔案", file_name)
service_client_socket.send(file_name.encode('gbk'))
# 等待客戶端確認,並準備傳送檔案內容
ack = service_client_socket.recv(1024)
if ack == b'ok':
file_path = share_dir + "/" + file_name
# 呼叫傳輸任務,向客戶端傳送檔案
read_send_task(file_path, service_client_socket)
flag = service_client_socket.recv(1024).decode('gbk')
if flag == "1":
print("開始傳送下一個檔案")
continue


# 主函式入口
if __name__ == '__main__':
# 設定檔案共享目錄
share_dir = "/home/test"
# 建立tcp套接字
file_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設定埠複用
file_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 繫結ip和埠
file_server_socket.bind(("", 5858))
# 設定監聽
file_server_socket.listen(128)
# 接收客戶端連線請求,返回新的套接字服務於客戶端
service_client_socket, ip_port = file_server_socket.accept()
# 獲取共享目錄的檔案列表,轉換為str型別,傳送給客戶端
file_list = os.listdir(share_dir)
file_str = ",".join(file_list)
service_client_socket.send(file_str.encode('gbk'))
# 接收客戶端請求列表,並向客戶端傳送相應檔案
send_task(service_client_socket, share_dir)
# 關閉新的套接字
service_client_socket.close()
# 關閉服務端套接字
file_server_socket.close()
#==========================================================================
#客戶端
import socket
import os


# 下載模式
def mode_opt(require_list, recv_file_list):
# 選擇要下載的模式
print("=" * 30)
print("1(下載單個或者多個檔案)")
print("2(下載資料夾的所有檔案)")
print("=" * 30)
opt_num = input("請選擇:")
# 單或多檔案下載,對檔名判斷是否存在,存在則加入請求列表
if opt_num == "1":
while True:
file_name = input("輸入要下載的檔名:")
if file_name in recv_file_list:
require_list.append(file_name)
else:
print("請求的檔案不存在!")
continue
opt_num1 = input("1 繼續新增,2 不添加了")
if opt_num1 == "1":
continue
elif opt_num1 == "2":
break
else:
print("輸入錯誤!")
break

# 所有檔案下載,將目錄列表直接複製給請求列表
if opt_num == "2":
for file_name in recv_file_list:
require_list.append(file_name)


# 迴圈接收服務端的發來的檔案
def recv_from_filesvr(client_socket, file_dir):
# 設定迴圈
while True:
# 等待接收伺服器傳送的檔名
file_name = client_socket.recv(1024).decode('gbk')
# 如果檔名不為空,拼接新的檔名
if file_name:
print("即將下載檔案", file_name)
# 向服務端傳送收到檔名的確認訊息,等待接收檔案內容
client_socket.send(b"ok")
# 拼接檔名
file_path = file_dir + '/' + file_name
# 開啟檔案並將接收的二進位制資料寫入檔案
with open(file_path, 'wb') as file:
while True:
recv_data = client_socket.recv(1024)
# 如果讀取內容不為空,且沒有出現trans_end標記,則持續向檔案寫入接收的內容,如果為空,退出迴圈
if recv_data:
# 如果讀取的內容出現標記,則剔除標記,將剩餘內容寫入檔案,並退出寫檔案迴圈
if recv_data.endswith(b'trans_end'):
recv_data = recv_data.replace(b'trans_end', b'')
file.write(recv_data)
print("%s下載完成!" % file_name)
# 向服務端傳送檔案寫入完成,等待發送下個檔案
client_socket.send("1".encode('gbk'))
print("準備下載下一個檔案")
break
else:
file.write(recv_data)
print("正在下載...")
else:
print("收到的檔名為空!程式結束")
break


# 建立tcp套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立連線
client_socket.connect(("127.0.0.1", 5858))
# 接收服務端的檔案列表
recv_file_list_data = client_socket.recv(1024)
recv_file_list = recv_file_list_data.decode('gbk').split(",")
print(recv_file_list)
# 指定目錄,接收服務端的檔案
file_dir = input("設定下載路徑:")
# 如果目錄存在直接下載,不存在則建立目錄
if not os.path.exists(file_dir):
print("目錄不存在,系統自動建立目錄")
os.mkdir(file_dir)
# 建立客戶端請求列表
require_list = []
# 呼叫下載模式
mode_opt(require_list, recv_file_list)
print(require_list)
print("hello")
# 向伺服器傳送要下載的檔案列表,將列表轉換為str傳送
require_str = ",".join(require_list)
client_socket.send(require_str.encode('gbk'))
# 呼叫接收函式,接收伺服器傳送的檔名和檔案內容
recv_from_filesvr(client_socket, file_dir)
# 關閉套接字
client_socket.close()