首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何确定在Python中使用HTTP下载的内容的文件名?

如何确定在Python中使用HTTP下载的内容的文件名?
EN

Stack Overflow用户
提问于 2016-05-05 21:11:47
回答 3查看 10K关注 0票数 23

我使用Python库的get函数下载了一个文件。为了存储该文件,我想确定web浏览器对其“保存”或“另存为.”的文件名。对话。

别紧张,对吧?我只需在响应对象上访问Content-Disposition header:

代码语言:javascript
运行
复制
import re
d = r.headers['content-disposition']
fname = re.findall("filename=(.+)", d)

但是仔细看看这个话题,就不会那么容易了:

根据RFC 6266第4.3节第4.1节中的语法,值可以是一个未引用的令牌(例如the_report.pdf)或一个引号字符串,该字符串也可以包含空格(例如"the report.pdf")和转义序列。此外,

当“文件名”和“文件名*”都出现在单个标题字段值中时,我们应该选择"filename*“而忽略"filename”。

然而,filename*的值是但是更复杂一些,而不是filename

此外,RFC似乎允许在=周围添加额外的空白。

因此,对于RFC中列出的例子,我希望得到以下结果:

  • 内容处理:附件;filename=example.html 文件名:example.html
  • 内容处理:内联;FILENAME= "an example.html“ 文件名:an example.html
  • 内容处理:附件;filename*= UTF-8‘%e2%82%ac%20% 文件名:€ rates
  • 内容处理:附件;filename=“欧元利率”;文件名*=utf-8‘’%e2%82%ac%20 文件名:€ rates在这里也是(而不是EURO rates,因为filename*优先)

现在,我可以很容易地将正则表达式调整为=周围的可变空格,但是让它处理所有其他变体也会变得相当笨拙。(通过引用和转义,我甚至不确定RegEx是否能涵盖所有的情况。也许他们可以,因为没有支撑嵌套的问题。)

所以,我需要实现一个完整的解析器吗,还是可以通过对库(可能是requests本身)的几次调用来根据RFC 6266确定文件名?由于RFC 6266是HTTP标准的一部分,我可以想象一些专门针对HTTP的库已经涵盖了这一点。(所以我有还询问了软件建议SE。)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-05-05 21:40:54

rfc6266库似乎完全满足了您的需要。它可以解析原始头、requests响应和urllib2响应。在PyPI上。

下面是一些例子:

代码语言:javascript
运行
复制
>>> import rfc6266, requests
>>> rfc6266.parse_headers('''Attachment; filename=example.html''').filename_unsafe
'example.html'
>>> rfc6266.parse_headers('''INLINE; FILENAME= "an example.html"''').filename_unsafe
'an example.html'
>>> rfc6266.parse_headers(
    '''attachment; '''
    '''filename*= UTF-8''%e2%82%ac%20rates''').filename_unsafe
'€ rates'
>>> rfc6266.parse_headers(
    '''attachment; '''
    '''filename="EURO rates"; '''
    '''filename*=utf-8''%e2%82%ac%20rates''').filename_unsafe
'€ rates'
>>> r = requests.get('http://example.com/€ rates')
>>> rfc6266.parse_requests_response(r).filename_unsafe
'€ rates'

不过,请注意:这个库不喜欢标题中的非标准空格。

票数 15
EN

Stack Overflow用户

发布于 2018-07-28 10:27:01

如果你真的不需要utf-8的结果

代码语言:javascript
运行
复制
def getFilename(s):
  fname = re.findall("filename\*?=([^;]+)", s, flags=re.IGNORECASE)
  print fname[0].strip().strip('"')

但是如果utf-8是必须的

代码语言:javascript
运行
复制
def getFilename(s):
    fname = re.findall("filename\*=([^;]+)", s, flags=re.IGNORECASE)
    if not fname:
        fname = re.findall("filename=([^;]+)", s, flags=re.IGNORECASE)
    if "utf-8''" in fname[0].lower():
        fname = re.sub("utf-8''", '', fname[0], flags=re.IGNORECASE)
        fname = urllib.unquote(fname).decode('utf8')
    else:
        fname = fname[0]
    # clean space and double quotes
    print fname.strip().strip('"')

# example
getFilename('Attachment; filename=example.html')
getFilename('INLINE; FILENAME= "an example.html"')

getFilename("attachment;filename*= UTF-8''%e2%82%ac%20rates")
getFilename("attachment; filename=\"EURO rates\";filename*=utf-8''%e2%82%ac%20rates")

getFilename("attachment;filename=\"_____ _____ ___ __ ____ _____ Hekayt Bent.2017.mp3\";filename*=UTF-8''%D8%A7%D8%BA%D9%86%D9%8A%D9%87%20%D8%AD%D9%83%D8%A7%D9%8A%D8%A9%20%D8%A8%D9%86%D8%AA%20%D9%84%D9%80%20%D9%85%D8%AD%D9%85%D8%AF%20%D8%B4%D8%AD%D8%A7%D8%AA%D8%A9%20Hekayt%20Bent.2017.mp3")

结果

代码语言:javascript
运行
复制
example.html
an example.html
€ rates
€ rates
اغنيه حكاية بنت لـ محمد شحاتة Hekayt Bent.2017.mp3
票数 2
EN

Stack Overflow用户

发布于 2022-08-19 15:22:41

在2022年,似乎原始答案中推荐的Python模块原始答案已经被放弃了,并且不能真正使用较新版本的Python。

好消息是有一个替换模块(几个模块中的一个,但这个模块实际上是工作的!)名为pyrfc6266

它可以安装以下设备:

代码语言:javascript
运行
复制
pip install pyrfc6266

并以同样的方式:

代码语言:javascript
运行
复制
import pyrfc6266
pyrfc6266.parse_filename('attachment; filename="foo.html"')

代码语言:javascript
运行
复制
import requests
import pyrfc6266
response = requests.get('http://httpbin.org/response-headers?Content-Disposition=attachment;%20filename%3d%22foo.html%22')
pyrfc6266.requests_response_to_filename(response)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37060344

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档