2016-05-05 4 views
11

Я загружаю файл с использованием функции get библиотеки Python requests. Для хранения файла я хотел бы определить имя файла, который они будут использовать для веб-браузера для диалога «сохранить» или «сохранить как ...».Как определить имя файла, загруженного с помощью HTTP в Python?

Легко, правда? Я могу только get it from the Content-Disposition заголовок HTTP, доступный на объект ответа:

import re 
d = r.headers['content-disposition'] 
fname = re.findall("filename=(.+)", d) 

Но более пристально глядя на эту тему, это не , что легко:

Согласно RFC 6266 section 4.3, и грамматика в section 4.1, это может быть некорректный токен (например, the_report.pdf) или строка с кавычками, которая также может содержать пробелы (например, "the report.pdf") и escape-последовательности. Кроме того,

, когда оба «имя файла» и «имя файла *» присутствуют в одном значении поля заголовка, [мы] должны выбрать «имя файла *» и игнорировать «имя файла».

Значение filename*, однако, является yet a bit more complicated, чем один из filename.

Кроме того, RFC, похоже, допускает дополнительные пробелы вокруг =.

Таким образом, для examples listed in the 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 как filename* имеет преимущество)

Теперь, я мог бы легко адаптировать регулярное выражение для учета переменных пробельного вокруг =, но иметь его ручку все остальные варианты тоже будут довольно громоздкими. (При цитировании и побеге я даже не уверен, что RegEx может охватывать все случаи. Может быть, они могут, поскольку в нем нет привязки фигурной скобки.)

Итак, Мне нужно реализовать полномасштабный синтаксический анализатор , или я могу определить имя файла в соответствии с RFC 6266 несколькими звонками в библиотеку HTTP (возможно, requests)? Поскольку RFC 6266 является частью стандарта HTTP, я могу себе представить, что некоторые библиотеки, специализированные по HTTP, уже охватывают это. (Итак, у меня есть also asked on Software Recommendations SE.)

ответ

8

. Библиотека 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' 

Как примечание, хотя: эта библиотека делает не как нестандартном пробелы в заголовке.

+0

Что вы подразумеваете под «нестандартными пробелами»? Пробел в местах, где стандарт не допускает пробелов? Или пробелы UNICODE, которые не являются частью 7-разрядного ASCII? –

+0

@ das-g Не исследовали достаточно, чтобы сказать вам точно. Оказывается, у 'parse_headers' есть опция' relaxed', которая помогает с этим. Проверьте код [здесь] (https://github.com/g2p/rfc6266/blob/master/rfc6266.py#L209). – Kupiakos

Смежные вопросы