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

httpx POST上传文件加DigestAuth触发Errno32 Broken pipe错误原因咨询

问题原因
  • Digest认证默认采用质询-响应的交互流程:客户端第一次发起请求时默认不会携带认证头,服务端返回401 Unauthorized并携带WWW-Authenticate响应头告知认证算法、随机数等参数,客户端计算出正确摘要后再携带Authorization头重发请求。
  • 上传大文件时,很多服务端不会等待完整请求体传输完成,收到未带认证头的POST请求后会直接返回401并断开连接,此时客户端还在上传70MB的文件内容,对端已经关闭连接,就会抛出httpcore.WriteError: [Errno 32] Broken pipe错误。
  • GET请求没有请求体,第一次请求只发送请求头即可收到服务端的认证质询,重发也不会有额外的传输开销,因此可以正常执行。
  • 移除auth参数后,客户端不会触发自动重发逻辑,服务端会等待完整文件传输完成后再返回401,因此不会出现中途断连的报错。

另外你原有代码存在逻辑缺陷:创建了httpx.Client实例但实际调用的是顶层httpx.post方法,无法复用客户端的认证缓存,也会加剧该问题。

解决方案

方案1:预完成认证质询(最优)

先向目标地址发起一次无请求体的HEAD请求,提前完成认证交互拿到有效凭证,再上传文件避免第一次大文件传输被中途断连:

import httpx

headers = { 'action': 'upload' }
file = 'filename.zip'
auth = httpx.DigestAuth('user', 'password')
upload_url = 'http://192.168.10.10/upload'

with httpx.Client() as client:
    # 先发起HEAD请求完成认证握手,缓存有效凭证
    client.head(upload_url, auth=auth)
    # 直接上传文件,首次请求就会携带正确的认证头
    files = {'upload-file': open('files/' + file, 'rb')}
    r = client.post(upload_url, files=files, headers=headers)

方案2:使用可重读文件对象(仅适合测试)

如果服务端允许等待请求体传输完成再返回401,可以将文件指针重置逻辑加入,保证重发请求时可以重新读取文件内容:

import httpx

headers = { 'action': 'upload' }
file = 'filename.zip'
auth = httpx.DigestAuth('user', 'password')
upload_url = 'http://192.168.10.10/upload'

with open('files/' + file, 'rb') as f:
    with httpx.Client(auth=auth) as client:
        f.seek(0) # 每次请求前重置文件指针到开头
        files = {'upload-file': f}
        r = client.post(upload_url, files=files, headers=headers)

该方案会传输两次完整的70MB文件,带宽开销加倍,不建议生产环境使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 03:18:03