You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python实现多文件传输 解决仅能传输单文件的问题

问题根因
  • 接收端仅支持单次文件接收:接收端和发送端建立连接后,只会执行一次文件接收逻辑,处理完第一个文件后就进入等待用户输入退出的状态,完全不会处理后续发送的第二个文件数据,这是第二次传输看不到文件的核心原因。
  • TCP粘包风险:当前发送逻辑是连续发送文件名、文件大小的字节流,没有明确的边界分隔,一旦数据量累计触发TCP粘包,接收端会把文件名和文件大小的数据读混,直接导致文件解析失败。
修复代码

发送端修改后代码

import os
import shutil
import socket
import struct

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((socket.gethostname(), 22222))
sock.listen(5)
print("Host Name: ", sock.getsockname())

client, addr = sock.accept()
print(f"已连接客户端:{addr}")

print("当你想要停止上传文件时输入 -> STOP <-")
while True:
    original = input("Filepath:")
    if original == "STOP":
        # 发送停止标识告知接收端结束传输
        client.send(struct.pack('i', 0))
        break
    if not os.path.exists(original):
        print("文件路径不存在,请重新输入")
        continue
    filename = os.path.basename(original)
    target = r'C:\Users\Gasper\Desktop\transfer\filename'
    path = target.replace('filename', filename)
    shutil.copy(original, path)

    file_size = os.path.getsize(path)
    # 用struct打包固定长度头部,解决粘包:先传文件名长度,再传文件名,再传文件大小
    filename_bytes = filename.encode()
    client.send(struct.pack('i', len(filename_bytes)))
    client.send(filename_bytes)
    client.send(struct.pack('q', file_size))

    # 发送文件内容
    with open(path, "rb") as file:
        while True:
            data = file.read(1024)
            if not data:
                break
            client.sendall(data)
    os.remove(path)
    print(f"{filename} 传输完成")

print("所有文件传输完成!")
input("按回车键退出...")
sock.close()

接收端修改后代码

import socket
import os
import struct

host = input("Host Name: ")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    sock.connect((host, 22222))
    print("连接成功")
except:
    print("无法连接到服务端")
    exit(0)

# 提前创建接收目录避免报错
if not os.path.exists("./rec"):
    os.makedirs("./rec")

while True:
    # 先接收文件名长度,为0代表传输结束
    filename_len = struct.unpack('i', sock.recv(4))[0]
    if filename_len == 0:
        break
    # 接收文件名
    file_name = sock.recv(filename_len).decode()
    # 接收文件大小
    file_size = struct.unpack('q', sock.recv(8))[0]

    recv_size = 0
    with open(os.path.join("./rec", file_name), "wb") as file:
        while recv_size < file_size:
            # 每次最多读剩余需要接收的大小,避免多读下一个文件的头部
            chunk = sock.recv(min(1024, file_size - recv_size))
            if not chunk:
                break
            file.write(chunk)
            recv_size += len(chunk)
    print(f"{file_name} 接收完成,大小:{recv_size}字节")

print("所有文件传输完成!")
input("按回车键退出...")
sock.close()
验证说明

修改后发送端可以连续输入多个文件路径传输,全部传完输入STOP即可结束,接收端会自动接收所有传输的文件存到rec目录下。

内容的提问来源于stack exchange,提问作者Gasper Melansek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:18:01