socket實現ftp文件的上傳和下載
server端代碼:
import socket
import json
import struct
import os
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.bind(('127.0.0.1', 8021))
soc.listen(5)
# 上傳函數
def uploading_file():
while True:
try:
ftp_dir = r'F:\shpython11\pycharmwork\first_project\study_start\day32\ftp_dir'
if not os.path.isdir(ftp_dir): # 這個是作為我們上傳了之后的文件放在這個位置,你改成自己本地的
os.mkdir(ftp_dir)
head_bytes_len = conn.recv(4) # 拿到struct后的頭長度
head_len = struct.unpack('i', head_bytes_len)[0] # 取出真正的頭長度
# 拿到真正的頭部內容
head_bytes = conn.recv(head_len)
# 反序列化后取出頭
head = json.loads(head_bytes)
file_name = head['file_name']
file_path = os.path.join(ftp_dir,file_name)
data_len = head['data_len']
with open(file_path, 'wb') as fw:
while data_len > 1024:
fw.write(conn.recv(1024))
data_len -= 1024
else:
fw.write(conn.recv(data_len))
conn.send(f'上傳文件 {file_name} 成功'.encode('utf8'))
except Exception:
break
while True:
print('等待客戶端連接。。。')
conn, addr = soc.accept()
print('客戶端已連接:', addr)
choice = conn.recv(1).decode('utf8')
if choice == 'q':
break
if choice == '1':
print('客戶端選擇了ftp上傳服務')
uploading_file()
elif choice == '2':
print('客戶端選擇了ftp下載服務')
while True:
try:
ftp_dir = r'F:\shpython11\pycharmwork\first_project\study_start\day32\ftp_dir'
if not os.path.isdir(ftp_dir): # 這個是作為我們上傳了之后的文件放在這個位置,你改成自己本地的
os.mkdir(ftp_dir)
file_list = os.listdir(ftp_dir)
head = {'file_list': file_list}
head_bytes = json.dumps(head).encode('utf8')
head_bytes_len = struct.pack('i', len(head_bytes))
conn.send(head_bytes_len)
conn.send(head_bytes)
client_head_bytes_len = conn.recv(4)
client_head_len = struct.unpack('i', client_head_bytes_len)[0]
client_head_bytes = conn.recv(client_head_len)
client_head = json.loads(client_head_bytes)
choice = client_head['choice']
file_name = file_list[int(choice)]
file_path = os.path.join(ftp_dir, file_name)
with open(file_path, 'rb') as fr:
data = fr.read()
server_head = {'data_len': len(data), 'file_name': file_name} # 自定義頭
server_head_bytes = json.dumps(server_head).encode('utf8')
server_head_bytes_len = struct.pack('i', len(server_head_bytes))
conn.send(server_head_bytes_len)
conn.send(server_head_bytes)
conn.send(data)
conn.send(f'下載文件 {file_name} 成功'.encode('utf8'))
except Exception:
break
conn.close()
soc.clone()
client端代碼:
import socket
import os
import struct
import json
client_soc = socket.socket()
client_soc.connect(('127.0.0.1',8021))
# 獲取文件夾下的文件
def get_file_list(file_path):
if os.path.exists(file_path):
if os.path.isfile(file_path):
return True,file_path
else:
file_list = os.listdir(file_path)
if file_list==[]:
return False,'當前文件夾為空,請重新選擇'
else:
return True,file_list
else:
return False,'你輸入的文件路徑不對'
# 上傳函數
def uploading_file():
print('歡迎進入ftp文件上傳系統')
while True:
dir_path = input('請輸入文件所在的文件夾路徑或文件路徑(輸入q退出):')
if dir_path == 'q':
print('你選擇了退出上傳系統')
break
flag, dir_list = get_file_list(dir_path)
if flag:
if os.path.isfile(dir_path):
file_name = dir_path.split('\\')[-1]
file_path = dir_path
else:
for ind, file in enumerate(dir_list):
print(f'文件編號:{ind} 對應的文件名為:{file}')
choice = input('請輸入文件編號進行上傳:').strip()
choice = int(choice)
file_name = dir_list[choice]
file_path = os.path.join(dir_path, file_name)
with open(file_path,'rb') as fr:
data = fr.read()
head = { 'data_len': len(data),'file_name':file_name} # 自定義頭
head_bytes = json.dumps(head).encode('utf8')
head_bytes_len = struct.pack('i',len(head_bytes))
client_soc.send(head_bytes_len)
client_soc.send(head_bytes)
client_soc.send(data)
msg = client_soc.recv(1024)
print(msg.decode('utf8'))
else:
print('你輸入的文件路徑不存在')
# 下載函數
def download():
print('歡迎來到ftp下載系統')
head_bytes_len = client_soc.recv(4)
head_len = struct.unpack('i', head_bytes_len)[0]
head_bytes = client_soc.recv(head_len)
head = json.loads(head_bytes)
file_list = head['file_list']
if file_list == []:
print('當前ftp中無文件可下載,等待上傳中')
else:
print('當前ftp中有如下文件')
for ind,file in enumerate(file_list):
print(f'文件編號:{ind} 對應的文件名為:{file}')
choice = input('請選擇要下載文件的編號:')
choice_head = {'choice':choice} # 自定義頭
choice_head_bytes = json.dumps(choice_head).encode('utf8')
choice_head_bytes_len = struct.pack('i', len(choice_head_bytes))
client_soc.send(choice_head_bytes_len)
client_soc.send(choice_head_bytes)
# 接收用戶傳遞過來的文件
client_head_bytes_len = client_soc.recv(4) # 拿到struct后的頭長度
client_head_len = struct.unpack('i', client_head_bytes_len)[0] # 取出真正的頭長度
# 拿到真正的頭部內容
client_head_bytes = client_soc.recv(client_head_len)
# 反序列化后取出頭
client_head = json.loads(client_head_bytes)
file_name = client_head['file_name']
data_len = client_head['data_len']
with open(file_name, 'wb') as fw:
while data_len > 1024:
fw.write(client_soc.recv(1024))
data_len -= 1024
else:
fw.write(client_soc.recv(data_len))
msg = client_soc.recv(1024)
print(msg.decode('utf8'))
while True:
msg = '''
1.文件上傳
2.文件下載
q.退出系統
'''
print(msg)
choice = input('請做出你的選擇:').strip()
client_soc.send(choice.encode('utf8'))
if choice == 'q':
print('你選擇了退出系統')
break
if choice == '1':
uploading_file()
elif choice == '2':
download()