как определить имя файла контента, загруженного с помощью HTTP в Python?
я загружаю файл с помощью get
функция Python requests
библиотека. Для хранения файла я хотел бы определить имя файла, как веб-браузер для его "сохранить" или "сохранить как"...' диалог.
легко, верно? Я могу просто получить его от Content-Disposition
заголовок HTTP, доступный на объекте ответа:
import re
d = r.headers['content-disposition']
fname = re.findall("filename=(.+)", d)
но, присмотревшись к этой теме более внимательно, это не это легко:
по данным RFC 6266 раздел 4.3, а грамматика в 4.1, значение может быть маркером без кавычек (например,the_report.pdf
) или строка с кавычками, которая также может содержать пробелы (например,"the report.pdf"
) и escape-последовательности. Далее,
когда оба "filename" и "filename*" присутствуют в одном значении поля заголовка, [мы] должны выбрать "filename*"и игнорировать "filename".
значение filename*
, хотя, это еще немного сложнее, чем filename
.
кроме того, RFC, похоже, допускает дополнительные пробелы вокруг =
.
таким образом, за примеры, перечисленные в RFC, я хотел бы получить следующие результаты:
-
имя файла:Content-Disposition: Attachment; filename=example.html
example.html
-
имя файла:Content-Disposition: INLINE; FILENAME= "an example.html"
an example.html
-
имя файла:Content-Disposition: attachment; filename*= UTF-8''%e2%82%ac%20rates
€ rates
-
имя файла:Content-Disposition: attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates
€ rates
здесь тоже (неEURO rates
, asfilename*
берет верх)
теперь я мог бы легко адаптировать регулярное выражение для учета переменных пробелов вокруг =
, но имея его обрабатывать все другие варианты, тоже будет довольно громоздким. (С цитированием и побегом я даже не уверен, что RegEx может охватить все случаи. Может быть, они и смогут, так как в этом нет необходимости.)
так должен ли я реализовать полномасштабный парсер или могу Я определяю имя файла в соответствии с RFC 6266 несколькими вызовами библиотеки HTTP (может быть )? Поскольку RFC 6266 является частью стандарта HTTP, я мог бы представить, что некоторые библиотеки, специализирующиеся на HTTP, уже охватывают это. (Я также спросил О рекомендациях программного обеспечения SE.)
2 ответов
на rfc6266
библиотека, похоже, делает именно то, что вам нужно. Он может анализировать необработанные заголовки,requests
ответы, а urllib2
ответы. Это PyPI.
примеры:
>>> 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'
как Примечание, хотя: это библиотека не как нестандартные пробелы в заголовке.
Если вам действительно не нужен результат в utf-8
def getFilename(s):
fname = re.findall("filename\*?=([^;]+)", s, flags=re.IGNORECASE)
print fname[0].strip().strip('"')
но если UTF-8 является обязательным
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")
результат
example.html
an example.html
€ rates
€ rates
اغنيه حكاية بنت لـ محمد شحاتة Hekayt Bent.2017.mp3