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

使用HTTP分块编码上传文件时遭遇SSL错误

分块编码上传文件触发SSL错误的原因与解决思路

尝试用分块编码上传文件时遇到以下SSL错误:

urllib3.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:2423)

初始实现代码:

from io import BytesIO

import requests

from werkzeug.datastructures import FileStorage

def test_upload_large_file():
    file_data = BytesIO(b'0' * (25 * 1024 * 1024))

    file = FileStorage(stream=file_data, filename='test.txt')

    headers = {'Transfer-Encoding': 'chunked'}

    url = "<url>"

    response = requests.post(url, headers=headers, files={'file': file})

    print(response.status_code)
    
    assert response.status_code == 200


test_upload_large_file()

改用Content-Type: multipart/form-data后上传正常,但重写本地文件读取的分块上传代码仍报相同错误:

import requests

def upload_file_chunked(url, file_path, chunk_size):
    with open(file_path, 'rb') as file:
        headers = {'Transfer-Encoding': 'chunked'}
        response = requests.post(url, headers=headers, data=file, stream=True)

    print("Response Code:", response.status_code)
    print("Response:", response.text)

# Example usage

url = "<url>"
file_path = "<file-path>"
chunk_size = 1024  # Specify the desired chunk size in bytes
upload_file_chunked(url, file_path, chunk_size)

问题根源分析

  1. requests库自动处理逻辑冲突
    当你手动设置Transfer-Encoding: chunked同时使用files参数时,requests会自动生成multipart/form-data类型的请求。手动添加的分块编码头会和库的自动处理逻辑冲突,导致请求格式畸形。服务器无法解析这种异常请求,会提前关闭连接,最终触发SSL层的EOF错误(这是表象,本质是请求格式不符合预期)。

  2. 分块编码与multipart/form-data的兼容性问题
    虽然HTTP/1.1标准支持分块编码,但很多服务器在处理multipart/form-data请求时,并不期望叠加分块编码——multipart本身已经有边界分割机制,叠加分块会让请求结构过于复杂,部分服务器无法正确解析,直接终止连接。

  3. SSL错误的本质并非加密问题
    你看到的SSL错误只是结果,核心原因是请求格式错误导致服务器提前断开SSL连接,而非证书验证、加密算法等SSL本身的问题。


解决办法

  1. 让requests自动处理分块编码
    requests在处理大文件上传时,若使用stream=True并传入文件对象,会自动启用分块编码,无需手动添加Transfer-Encoding头:

    import requests
    
    def upload_file_chunked(url, file_path):
        with open(file_path, 'rb') as file:
            # 移除手动设置的Transfer-Encoding头
            response = requests.post(url, data=file, stream=True)
    
        print("Response Code:", response.status_code)
        print("Response:", response.text)
    
    # 使用示例
    url = "<url>"
    file_path = "<file-path>"
    upload_file_chunked(url, file_path)
    
  2. 表单式文件上传直接用files参数
    如果需要上传带文件名等元信息的表单式文件,直接使用files参数即可,requests会自动处理大文件的分块逻辑:

    from io import BytesIO
    import requests
    from werkzeug.datastructures import FileStorage
    
    def test_upload_large_file():
        file_data = BytesIO(b'0' * (25 * 1024 * 1024))
        file = FileStorage(stream=file_data, filename='test.txt')
        url = "<url>"
        # 移除手动设置的Transfer-Encoding头
        response = requests.post(url, files={'file': file})
        print(response.status_code)
        assert response.status_code == 200
    
    test_upload_large_file()
    
  3. 确认服务器支持的上传格式
    部分服务器可能仅接受multipart/form-data格式的文件上传,不支持原始分块上传。如果必须用分块编码上传原始文件,需确认服务器是否接受该格式,必要时添加Content-Type: application/octet-stream头。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:05:16