Python Requests发送POST文件请求返回503状态码问题排查
问题排查与解决方案
可能原因及对应处理步骤
1. 请求超时时间设置过短
requests默认超时时间偏短,即便5MB文件不算大,内部网络的临时波动也可能触发超时。手动设置更长的超时阈值试试:
with open(filepath, "rb") as f: data = {"name": experiment_id + ".zip", "content": f} calcscore_url = f"{settings.CALCSCORE_URL}/api/hive/experiment/{experiment_id}/roi" # 可根据实际情况调整超时时长,比如设置15秒 response = requests.post(calcscore_url, files=data, timeout=15)
2. 请求头与Postman存在差异
Postman会自动添加部分标准请求头,而requests默认的请求头可能不符合服务器当前的校验逻辑。复制你Postman中的请求头,在代码里手动配置:
headers = { "User-Agent": "PostmanRuntime/7.32.3", # 替换为你Postman实际使用的User-Agent # 补充其他Postman中存在的请求头,注意不要手动设置multipart/form-data,files参数会自动处理 } response = requests.post(calcscore_url, files=data, headers=headers, timeout=15)
3. 文件指针位置异常
如果文件对象此前有过读取操作,指针可能停留在文件末尾,导致上传内容为空或不完整。确保文件指针回到起始位置:
with open(filepath, "rb") as f: f.seek(0) # 将文件指针重置到开头 data = {"name": experiment_id + ".zip", "content": f} calcscore_url = f"{settings.CALCSCORE_URL}/api/hive/experiment/{experiment_id}/roi" response = requests.post(calcscore_url, files=data, timeout=15)
4. 内部代理/防火墙规则变更
虽然GET请求正常,但带文件的POST请求可能被新的防火墙或代理规则拦截。如果公司有内部代理,在requests中指定代理:
proxies = { "http": "http://internal-proxy:port", "https": "https://internal-proxy:port", } response = requests.post(calcscore_url, files=data, proxies=proxies, timeout=15)
如果不清楚代理信息,检查Postman的代理设置——Postman可能默认使用了系统代理,而requests没有自动继承。
5. 服务器端并发/负载限制
服务器可能对同一客户端的并发连接数做了限制,或近期负载过高导致响应缓慢。添加重试机制提升成功率:
from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry # 构建带重试逻辑的会话 session = requests.Session() retry_strategy = Retry( connect=3, backoff_factor=0.5, # 重试间隔时间递增 ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://", adapter) session.mount("https://", adapter) with open(filepath, "rb") as f: data = {"name": experiment_id + ".zip", "content": f} calcscore_url = f"{settings.CALCSCORE_URL}/api/hive/experiment/{experiment_id}/roi" response = session.post(calcscore_url, files=data, timeout=15)
额外排查手段
- 开启分块上传,避免一次性将文件加载到内存:
response = requests.post(calcscore_url, files=data, timeout=15, stream=True)
- 开启requests调试日志,对比Postman的请求细节,定位差异:
import logging import http.client http.client.HTTPConnection.debuglevel = 1 logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) requests_log = logging.getLogger("requests.packages.urllib3") requests_log.setLevel(logging.DEBUG) requests_log.propagate = True # 执行POST请求,控制台会输出完整的请求/响应日志
内容的提问来源于stack exchange,提问作者Mazhar Ali
相关产品推荐
相关产品推荐

