【1011 | Day 42】socket实现ftp文件的上传和下载

1. 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()

2. 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()
posted @ 2019-10-11 21:16  fxyadela  阅读(169)  评论(0编辑  收藏  举报