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

如何从不带文件名的URL下载文件并识别文件类型与原始文件名

动态URL文件下载问题解决方案

以下是可直接运行的完整实现代码,同时覆盖两个问题的解决需求:

import requests
import os
from cgi import parse_header

# 配置要下载的URL
url = "https://procurement-notices.undp.org/view_file.cfm?doc_id=257280"
# url = "https://readthedocs.org/projects/python-guide/downloads/pdf/latest/"

# 配置文件保存目录
save_dir = "./downloads"
os.makedirs(save_dir, exist_ok=True)

# 发送请求,开启重定向跟随、流式下载(适合大文件),添加超时避免卡死
resp = requests.get(url, allow_redirects=True, stream=True, timeout=30)
resp.raise_for_status()  # 请求出错直接抛出异常,避免保存错误页面内容

# 1. 解析原始文件名
filename = None
content_disposition = resp.headers.get("Content-Disposition")
if content_disposition:
    disposition, params = parse_header(content_disposition)
    if "filename" in params:
        filename = params["filename"]
    # 适配UTF-8编码的非英文文件名场景
    elif "filename*" in params:
        filename_encoding, _, filename = params["filename*"].split("'", 2)
        filename = filename.encode('latin-1').decode(filename_encoding)

# 2.  fallback逻辑:未拿到原始文件名时,通过Content-Type推断后缀
if not filename:
    # 常见Content-Type到后缀的映射,可根据需求自行扩展
    content_type = resp.headers.get("Content-Type", "")
    type_suffix_map = {
        "application/pdf": ".pdf",
        "application/msword": ".doc",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
        "application/vnd.ms-excel": ".xls",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
        "text/plain": ".txt",
        "application/zip": ".zip"
    }
    suffix = type_suffix_map.get(content_type, ".bin")  # 未知类型默认用.bin后缀
    filename = f"download_file{suffix}"

# 拼接完整保存路径
save_path = os.path.join(save_dir, filename)

# 流式写入文件,避免大文件占用过多内存
with open(save_path, "wb") as f:
    for chunk in resp.iter_content(chunk_size=8192):
        f.write(chunk)

print(f"文件已保存至:{save_path}")

问题1:如何提前判断返回的文件类型,使用正确后缀保存

  • 优先从响应头Content-Disposition的filename字段提取后缀,这是最准确的方式,和浏览器拿到的原始文件名后缀完全一致
  • 若响应头没有返回Content-Disposition,则通过Content-Type响应头匹配对应后缀,提前维护好常见的媒体类型和后缀的映射表即可,未知类型可以默认用.bin后缀避免错误

问题2:如何获取浏览器下载的原始文件名

浏览器展示的原始文件名绝大多数都存放在响应头的Content-Disposition字段中,格式一般为attachment; filename="xxx.docx",部分站点会用UTF-8编码的filename*=UTF-8''xxx.docx格式避免非英文文件名乱码,用标准库cgi模块的parse_header方法可以直接解析该字段的参数,不需要自己写正则匹配。

优化点说明

  • 加入stream=True流式下载,大文件不会一次性加载到内存,占用资源更低
  • 加入resp.raise_for_status(),4xx/5xx错误会直接抛出异常,避免把错误页面内容当成文件保存
  • 新增文件名编码适配、目录自动创建、超时配置等鲁棒性逻辑,适合生产环境使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 22:24:00