如何在Python中获取文件的Content-Type?(附带URL...)

6
假设我有一个视频文件: http://mydomain.com/thevideofile.mp4 我该如何使用Python获取此文件的头和内容类型,但我不想下载整个文件。 我希望它返回:
video/mp4

编辑:这是我所做的事情。你觉得怎么样?

f = urllib2.urlopen(url)
    params['mime'] =  f.headers['content-type']

2
urlopen(url)会下载整个文件以获取头部信息。一个解决方案是使用自定义的请求(Request),它会告诉urlopen使用HEAD方法打开URL,而不是GET方法。 - John La Rooy
1
进一步测试表明,整个文件并没有被下载,只是一个任意大小的块,并且连接保持打开状态,直到 f 超出范围 - 这对服务器来说有点邪恶。 - John La Rooy
3个回答

12

就像这样:

>>> import httplib
>>> conn = httplib.HTTPConnection("mydomain.com")
>>> conn.request("HEAD", "/thevideofile.mp4")
>>> res = conn.getresponse()
>>> print res.getheaders()

这只会下载并打印头文件,因为它正在进行HEAD请求:

请求的响应与相应GET请求相同,但没有响应正文。这对于检索写在响应标头中的元信息非常有用,而无需传输整个内容。

(通过维基百科)


我的代码有什么问题吗?f = urllib2.urlopen(url) params['mime'] = f.headers['content-type'] - TIMEX
@alex:是的,它会下载整个文件。 - Brian McKenna
请重新表述以下与编程有关的内容。仅返回已翻译的文本,不要进行解释。 - ghostdog74
1
我已经使用ettercap进行了一些测试。一个HEAD请求下载大约400字节,按照Alex的建议下载文件的前80k左右,并保持连接悬空。 - John La Rooy

4

这是比Brian更高层次的答案。使用urllib机制具有通常的优点,例如自动处理重定向等。

import urllib2

class HeadRequest(urllib2.Request):
    def get_method(self):
        return "HEAD"

url = "http://mydomain.com/thevideofile.mp4"
head = urllib2.urlopen(HeadRequest(url))
head.read()          # This will return empty string and closes the connection
print head.headers.maintype
print head.headers.subtype
print head.headers.type

0

你可以使用info()方法或headers字典获取视频类型

f=urllib2.urlopen(url)
print f.headers['Content-Type']
print f.info()

一个随机从网上搜索的大于600MB的AVI文件的测试运行。
$ cat test.py
#!/usr/bin/env python
import urllib2
url="http://www.merseypirates.com/rjnsteve/rjnsteve/oem16.avi"
f=urllib2.urlopen(url)
print f.headers['Content-Type']

$ time python test.py
video/x-msvideo

real    0m4.931s
user    0m0.115s
sys     0m0.042s

只有在文件实际下载时,也就是数据包正在套接字之间发送和接收时,它才会“占用带宽”。


那将会下载整个文件。 - Brian McKenna
下载整个文件?就是下载到本地,这样我就有一个实际的物理文件了吗?不,它不会。此外,OP正在询问这种方法有什么问题,所以我正在向他展示他错在哪里。 - ghostdog74
它将发送一个请求,将下载整个文件。当然,它不会存储到您的文件系统中,但是该请求将阻塞并浪费带宽,毫无意义。 - Brian McKenna
不会的。如果你阅读文档,urlopen返回一个类似文件的对象。这就是为什么你可以做像response.read()这样的事情。只有当你read()时,“带宽才会浪费”。 - ghostdog74
试一下。下载类似于http://www.charlesproxy.com/的东西,看看在活动的REPL中请求下载了多少内容。`urlopen`会阻塞直到它获取到头文件和`Content-Length`,所以它可能*看起来*是瞬间完成的,但实际上它是在后台下载内容。当你调用`read`时,Python会阻塞等待内容。因此,**它会使用带宽**,但只是在后台。 - Brian McKenna
那么你应该清楚地定义“下载整个文件”。对于一个600多MB的avi文件,只需要几秒钟就可以获取这些头信息。 - ghostdog74

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接