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

Python3通过TCP套接字实现无临时文件落盘的加密文件传输

Python TCP套接字无临时文件加密文件传输实现

核心思路为全程内存流式分块处理,读文件块→内存加密→直接发送,不落地临时文件,内存占用恒定,适配现有协议架构。

原有代码缺陷修复

当前代码中send_raw/recv_raw存在三个影响文件传输的核心问题:

  • 强制将二进制字节转字符串解码,会损坏图片、可执行程序等非文本文件
  • recv_raw仅调用一次recv,TCP是流式协议,单次调用无法保证收全完整数据,会出现粘包截断
  • 固定缓冲区大小无法适配大尺寸数据传输

先替换这两个函数的实现,兼容二进制数据、解决粘包问题:

def send_raw(content_type, Bytes_, salt=new_salt()):
    seperator = b"<|SEPERATE|>"
    # 全程用字节处理,不做强制编解码
    to_send = content_type.encode() + seperator + Bytes_ + seperator + salt.encode()
    if encryption:
        f = Fernet(key)
        to_send = f.encrypt(to_send)
    # 先发帧长度,解决粘包
    frame_len = str(len(to_send)).encode()
    conn.send(frame_len + b"\n")
    conn.sendall(to_send)

def recv_raw(BufferSize=4096):
    seperator = b"<|SEPERATE|>"
    # 先读帧长度
    len_data = b""
    while b"\n" not in len_data:
        len_data += conn.recv(1)
    frame_len = int(len_data.decode().strip())
    # 按长度循环读完整帧
    data = b""
    while len(data) < frame_len:
        chunk = conn.recv(min(BufferSize, frame_len - len(data)))
        if not chunk:
            raise ConnectionError("连接断开")
        data += chunk
    if encryption:
        f = Fernet(key)
        data = f.decrypt(data)
    splitted = data.split(seperator, 2) # 只拆分前两个分隔符,避免内容中出现分隔符导致解析错误
    content_type = splitted[0].decode()
    Bytes_ = splitted[1]
    salt = splitted[2].decode()
    return {"content_type": content_type, "bytes": Bytes_}

send_file指令服务端实现

直接在代码标注# CODE GOES HERE的位置填入以下逻辑,全程无临时文件写入,分块流式加密发送:

if cmd.startswith("send_file"):
    # 解析发送路径,支持 send_file 本地文件路径 调用语法
    _, local_path = cmd.split(maxsplit=1)
    if not os.path.exists(local_path):
        print(f"错误:文件 {local_path} 不存在")
        continue
    file_name = os.path.basename(local_path)
    file_size = os.path.getsize(local_path)
    # 先发文件元信息控制帧,通知客户端准备接收
    meta = json.dumps({
        "file_name": file_name,
        "file_size": file_size
    }).encode()
    send_raw("file_start", meta)
    # 等待客户端就绪确认
    ack = recv_raw()
    if ack["content_type"] != "file_ack":
        print("客户端未就绪,取消传输")
        continue
    # 分块读文件、内存加密、直接发送,块大小设为1MB,平衡内存占用和传输效率
    chunk_size = 1024 * 1024
    sent = 0
    with open(local_path, "rb") as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            send_raw("file_chunk", chunk)
            sent += len(chunk)
            print(f"\r传输进度:{sent/file_size*100:.1f}%", end="")
    # 发送结束帧
    send_raw("file_end", b"")
    # 等待客户端接收完成确认
    finish_ack = recv_raw()
    if finish_ack["content_type"] == "file_complete":
        print(f"\n文件 {file_name} 发送完成")
    else:
        print(f"\n文件传输异常")
    # 跳过后续普通命令发送逻辑
    continue

客户端对应适配逻辑

需要在客户端消息处理循环里新增三类消息的处理,同样全程内存操作,不产生临时文件:

  • 收到file_start帧:解析文件名、大小,回传file_ack确认,初始化接收字节计数器
  • 收到file_chunk帧:把解密后的块直接写入目标保存路径,更新接收进度
  • 收到file_end帧:校验接收总字节数和元信息的文件大小是否一致,回传file_complete确认

方案优势

  • 全程无临时磁盘写入,不会占用额外磁盘空间
  • 分块处理时内存占用恒定为1MB左右,传输几十GB级大文件也不会出现内存溢出
  • 完全复用现有Fernet加密逻辑,所有文件数据全程密文传输
  • 修复了原有代码的粘包、二进制兼容问题,普通命令执行、信息采集功能不受影响

内容的提问来源于stack exchange,提问作者Ryder R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:30:58