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

aiohttp异步下载URL返回404错误但同步请求及浏览器访问正常

问题根因

  • 核心差异是aiohttp和requests对已编码URL的处理逻辑不同:你传入的目标URL中已经包含URL编码后的内容(如路径中的EO%3AEUM%3ADAT),requests不会对已编码的URL做二次处理,而aiohttp默认会对URL再次编码,会把百分号%转义为%25,最终请求的路径和原始路径不一致,API网关无法匹配到对应资源,因此返回404。
  • 次要可能的原因:部分API网关会拦截aiohttp默认的User-Agent请求头,拒绝响应。

解决方法

方案1:关闭URL自动编码(推荐,适配当前场景)

修改_get函数,使用yarl.URL构造请求地址并开启encoded=True参数,避免二次编码:

# 先导入yarl的URL类
from yarl import URL

async def _get(
    url: Union[Path, str],
    timeout: aiohttp.ClientTimeout = aiohttp.ClientTimeout(),
    **kwargs: Union[aiohttp.BasicAuth, Dict[str, Any]]
) -> bytes:
    kwargs["timeout"] = timeout
    # 构造URL时指定encoded=True,保留原始编码不做二次处理
    request_url = URL(str(url), encoded=True)
    async with aiohttp.request("GET", request_url, **kwargs) as response:
        # 可添加打印验证最终请求地址是否符合预期
        # print(f"最终请求地址:{response.url}")
        return await response.read()

方案2:主动设置请求头

如果修改URL后仍然报错,可以给请求添加和浏览器/requests一致的User-Agent头,避免被网关拦截:

# 调用get函数时传入headers参数
custom_headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
get(remote_file, headers=custom_headers)

方案3:拆分查询参数

也可以把URL中的access_token拆分出来作为params参数传入,避免URL编码问题:

# 原始URL去掉query部分
remote_file = 'https://api.eumetsat.int/data/download/collections/EO%3AEUM%3ADAT%3AMSG%3AHRSEVIRI/products/MSG4-SEVI-MSG15-0100-NA-20210916121242.731000000Z-NA'
# 单独传token参数
params = {"access_token": "43e1b232-02ed-30db-9d17-363f00a4a1f0"}
get(remote_file, params=params)

内容的提问来源于stack exchange,提问作者dl.meteo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:06:05