python文件传输 带进度条

发布于:2025-06-12 ⋅ 阅读:(19) ⋅ 点赞:(0)
# -*- coding: utf-8 -*-
"""
文件传输程序(带进度条版本)

功能说明:
服务端:接收文件
客户端:发送文件

使用方法:
1. 启动服务端(接收文件):
   python file_transfer.py server [监听IP] [监听端口]

2. 发送文件到指定地址:
   python file_transfer.py 文件路径 [服务器IP] [服务器端口]

示例:
   # 监听所有接口的8888端口
   python file_transfer.py server 0.0.0.0 8888
   
   # 发送文件到指定服务器的8888端口
   python file_transfer.py data.txt 192.168.1.100 8888
"""
import socket
import os
from tqdm import tqdm
import threading
import time
def run_server(host='127.0.0.1', port=12345):
    """
    文件接收服务端
    :param host: 监听地址
    :param port: 监听端口
    """
    # 创建TCP socket
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((host, port))
    server_socket.listen(10)
    
    print(f"[*] 监听 {host}:{port}")
    
    try:
        while True:
            client_socket, addr = server_socket.accept()
            print(f"[+] 连接来自 {addr}")
            # 为每个客户端创建新线程
            client_thread = threading.Thread(
                target=handle_client,
                args=(client_socket, addr)
            )
            client_thread.start()

    except KeyboardInterrupt:
        print("\n[!] 服务端关闭")
    finally:
        server_socket.close()

# 新增客户端处理函数
def handle_client(client_socket, addr):
    """处理单个客户端连接"""
    try:
        # 接收文件名
        file_name = client_socket.recv(1024).decode('utf-8')
        print(f"[*] 接收文件: {file_name}")
        # 新增文件存在检查
        if os.path.exists(file_name):
            client_socket.sendall(b'FileExists')
            time.sleep(0.1)  # 新增短暂延迟
            print(f"[!] 文件 {file_name} 已存在,拒绝接收")
            return
            
        client_socket.send(b'FilenameReceived')
        
        # 接收文件大小
        file_size = int(client_socket.recv(1024).decode('utf-8'))
        client_socket.send(b'Filesize received')
        
        # 接收文件内容(保持原有逻辑)
        progress = tqdm(total=file_size, unit='B', unit_scale=True, desc=f"接收 {file_name}")
        with open(file_name, 'wb') as file:
            received_size = 0
            while received_size < file_size:
                data = client_socket.recv(1024)
                file.write(data)
                received_size += len(data)
                progress.update(len(data))
        
        progress.close()
        print(f"[√] 文件 {file_name} 接收完成")

    except Exception as e:
        print(f"[!] 客户端 {addr} 处理异常: {str(e)}")
    finally:
        client_socket.close()

def send_file(file_path, host='127.0.0.1', port=12345):
    """
    发送文件到服务端
    :param file_path: 要发送的文件路径
    :param host: 服务端地址
    :param port: 服务端端口
    """
    if not os.path.exists(file_path):
        print(f"[!] 文件 {file_path} 不存在")
        return
    
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    try:
        client_socket.connect((host, port))
        print(f"[*] 已连接到 {host}:{port}")
        
        # 发送文件名
        file_name = os.path.basename(file_path)
        print(f"[*] 准备发送文件: {file_name}")
        client_socket.send(file_name.encode('utf-8'))
        data = client_socket.recv(1024)  # 等待确认
        print(data)
        # 发送文件大小
        file_size = os.path.getsize(file_path)
        client_socket.send(str(file_size).encode('utf-8'))
        client_socket.recv(1024)  # 等待确认
        
        # 发送文件内容
        progress = tqdm(total=file_size, unit='B', unit_scale=True, desc=f"发送 {file_name}")
        with open(file_path, 'rb') as file:
            while True:
                data = file.read(1024)
                if not data:
                    break
                client_socket.send(data)
                progress.update(len(data))
        
        progress.close()
        print(f"[√] 文件 {file_name} 发送完成")  # 修复:移动到try块内部
    
    except Exception as e:
        print(f"[!] 错误发生: {str(e)}")
    finally:
        client_socket.close()

if __name__ == "__main__":
    # 使用示例
    import sys
    if len(sys.argv) > 1 and sys.argv[1] == 'server':
        # 解析服务端参数:python file_transfer.py server [IP] [PORT]
        server_host = sys.argv[2] if len(sys.argv) > 2 else '127.0.0.1'
        server_port = int(sys.argv[3]) if len(sys.argv) > 3 else 12345
        run_server(server_host, server_port)
    else:
        # 解析客户端参数:python file_transfer.py 文件路径 [IP] [PORT]
        if len(sys.argv) < 2:
            print("使用方法:")
            print("  接收文件: python file_transfer.py server [IP] [端口]")
            print("  发送文件: python file_transfer.py 文件路径 [IP] [端口]")
            sys.exit()
            
        file_path = sys.argv[1]
        send_host = sys.argv[2] if len(sys.argv) > 2 else '127.0.0.1'
        send_port = int(sys.argv[3]) if len(sys.argv) > 3 else 12345
        send_file(file_path, send_host, send_port)