如何安全地从URL获取文件扩展名?

49 投票
10 回答
51620 浏览
提问于 2025-04-16 10:29

考虑以下这些网址:

http://m3u.com/tunein.m3u
http://asxsomeurl.com/listen.asx:8024
http://www.plssomeotherurl.com/station.pls?id=111
http://22.198.133.16:8024

怎样才能正确判断文件的扩展名(.m3u/.asx/.pls)呢?很明显,最后一个没有扩展名。

补充说明:我忘了提到,m3u、asx 和 pls 是用于音频流的播放列表(文本文件),需要用不同的方式来解析。我们的目标是确定扩展名,然后把网址发送到合适的解析函数。例如,


url = argv[1]
ext = GetExtension(url)
if ext == "pls":
  realurl = ParsePLS(url)
elif ext == "asx":
  realurl = ParseASX(url)
(etc.)
else:
  realurl = url
Play(realurl)

GetExtension() 应该返回文件的扩展名(如果有的话),最好是在不连接到网址的情况下完成。

10 个回答

48

使用 requestsmimetypes 这两个工具来处理这个问题是最简单的。

import requests
import mimetypes

response = requests.get(url)
content_type = response.headers['content-type']
extension = mimetypes.guess_extension(content_type)

文件的扩展名是以点开头的。例如,extension 对于内容类型 'image/png' 来说,就是 '.png'

58

使用 urlparse 来从网址中提取路径,然后用 os.path.splitext 来获取文件的扩展名。

import os
try:
    import urlparse
except ImportError:
    from urllib.parse import urlparse

url = 'http://www.plssomeotherurl.com/station.pls?id=111'
path = urlparse.urlparse(url).path
ext = os.path.splitext(path)[1]

需要注意的是,文件的扩展名可能并不能准确反映文件的类型。HTTP 的 Content-Type 头信息可能更可靠。

25

真正正确的方法是根本不使用文件扩展名。你可以对相关的URL发起一个GET(或者HEAD)请求,然后查看返回的“Content-type”这个HTTP头信息来获取内容类型。文件扩展名并不可靠。

想了解更多信息和一些有用的MIME类型,可以查看MIME类型(IANA媒体类型)

撰写回答