2011-11-07 22 views
21

मैं मशीनीकरण के साथ और प्रतिक्रिया हेडर में वहाँ एक स्ट्रिंग है एक फाइल को डाउनलोड कर रहा हूँ में सामग्री-विन्यास से फ़ाइल नाम पाने के लिए? क्या मैं मन में है अब यह है:कैसे हेडर

filename = f[1]['Content-Disposition'].split('; ')[1].replace('filename=', '') 

लेकिन यह एक quick'n'dirty समाधान की तरह दिखता है। यह उद्धरण और यूआरएल फ़ाइल नाम पर बचने संभालती

import re 
filename = re.findall("filename=(\S+)", f[1]['Content-Disposition']) 

:

+0

बस एक चेतावनी के रूप में, फ़ाइल नाम उद्धृत किया जा सकता है (अधिकांश संदेश शीर्षकों की तरह) और बचने के दृश्य हैं। तो त्वरित स्ट्रिंग हैक समस्याओं का कारण बन सकता है। –

उत्तर

24

पहले से व्याकरण पर आधारित है द्वारा हेडर के मूल्य प्राप्त मशीनीकरण का उपयोग करके, बिल्टिन cgi मॉड्यूल का उपयोग करके हेडर को पार्स करें।

प्रदर्शित करने के लिए:

>>> import mechanize 
>>> browser = mechanize.Browser() 
>>> response = browser.open('http://example.com/your/url') 
>>> info = response.info() 
>>> header = info.getheader('Content-Disposition') 
>>> header 
'attachment; filename=myfilename.txt' 

हैडर मूल्य तो पार्स किया जा सकता:

>>> import cgi    
>>> value, params = cgi.parse_header(header) 
>>> value 
'attachment' 
>>> params 
{'filename': 'myfilename.txt'} 

params एक सरल dict है तो params['filename'] तुम क्या जरूरत है। इससे कोई फ़र्क नहीं पड़ता कि फ़ाइल नाम उद्धरण में लपेटा गया है या नहीं।

+0

यह नहीं कि यह फ़ाइल काम नहीं करता है, तो यह नहीं काम करता है, इस मामले में पैराम्स में' फ़ाइल नाम 'के बजाय' फ़ाइल नाम * 'होगा और आपको अनकोट करना होगा और फ़ाइल नाम को एक यूनिकोड स्ट्रिंग में डीकोड करें। –

0

मैं की तरह कुछ की कोशिश करेंगे।

+1

लेकिन यह एक स्ट्रिंग नहीं, एक स्ट्रिंग नहीं है, इसलिए आप शायद 'फ़ाइल नाम [0]' या कुछ चाहते हैं। इसके अलावा यह फ़ाइल नाम के हिस्से के रूप में उद्धरण देता है। तो वास्तव में एक कामकाजी उदाहरण नहीं है। – unkulunkulu

5

ये नियमित अभिव्यक्ति आरएफसी 6266 से व्याकरण पर आधारित हैं, लेकिन बिना स्वभाव के प्रकार के हेडर स्वीकार करने के लिए संशोधित, उदा। सामग्री-विस्थापन: फ़ाइल नाम = example.html

यानी [स्वभाव-प्रकार ";" ] स्वभाव-परम (";" स्वभाव-औषधि) */स्वभाव-प्रकार

यह कोटनाम के साथ और बिना फ़ाइल नाम पैरामीटर को संभाल देगा, और कोट्स में मूल्यों से उद्धृत जोड़े को अनदेखा करेगा, उदा। फ़ाइल नाम = "foo \" बार "-> foo" बार

यह फ़ाइल नाम बढ़ाया मापदंडों संभाल लेंगे * और एक फ़ाइल नाम क्रम में वे शीर्ष लेख में दिखाई देते हैं की परवाह किए बिना एक filename पैरामीटर से अधिक बढ़ाया पैरामीटर पसंद करते हैं *

यह स्ट्रिप्स फ़ोल्डर नाम की जानकारी, उदाहरण के लिए/etc/passwd -> passwd, और यह फ़ाइल नाम पैरामीटर (या हेडर, या पैरामीटर मान खाली स्ट्रिंग) की अनुपस्थिति में यूआरएल पथ से बेसनाम पर डिफ़ॉल्ट है

टोकन और qdtext नियमित अभिव्यक्ति आधारित हैं RFC 2616 से व्याकरण पर, mimeCharset और valueChars नियमित अभिव्यक्ति आरएफसी 5987 से व्याकरण पर आधारित हैं, और भाषा नियमित अभिव्यक्ति आरएफसी 5646

import re, urllib 
from os import path 
from urlparse import urlparse 

# content-disposition = "Content-Disposition" ":" 
#      disposition-type *(";" disposition-parm) 
# disposition-type = "inline" | "attachment" | disp-ext-type 
#      ; case-insensitive 
# disp-ext-type  = token 
# disposition-parm = filename-parm | disp-ext-parm 
# filename-parm  = "filename" "=" value 
#      | "filename*" "=" ext-value 
# disp-ext-parm  = token "=" value 
#      | ext-token "=" ext-value 
# ext-token   = <the characters in token, followed by "*"> 

token = '[-!#-\'*+.\dA-Z^-z|~]+' 
qdtext='[]-~\t !#-[]' 
mimeCharset='[-!#-&+\dA-Z^-z]+' 
language='(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}(?:-[A-Za-z]{3}){,2})?|[A-Za-z]{4,8})(?:-[A-Za-z]{4})?(?:-(?:[A-Za-z]{2}|\d{3}))(?:-(?:[\dA-Za-z]{5,8}|\d[\dA-Za-z]{3}))*(?:-[\dA-WY-Za-wy-z](?:-[\dA-Za-z]{2,8})+)*(?:-[Xx](?:-[\dA-Za-z]{1,8})+)?|[Xx](?:-[\dA-Za-z]{1,8})+|[Ee][Nn]-[Gg][Bb]-[Oo][Ee][Dd]|[Ii]-[Aa][Mm][Ii]|[Ii]-[Bb][Nn][Nn]|[Ii]-[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-[Ee][Nn][Oo][Cc][Hh][Ii][Aa][Nn]|[Ii]-[Hh][Aa][Kk]|[Ii]-[Kk][Ll][Ii][Nn][Gg][Oo][Nn]|[Ii]-[Ll][Uu][Xx]|[Ii]-[Mm][Ii][Nn][Gg][Oo]|[Ii]-[Nn][Aa][Vv][Aa][Jj][Oo]|[Ii]-[Pp][Ww][Nn]|[Ii]-[Tt][Aa][Oo]|[Ii]-[Tt][Aa][Yy]|[Ii]-[Tt][Ss][Uu]|[Ss][Gg][Nn]-[Bb][Ee]-[Ff][Rr]|[Ss][Gg][Nn]-[Bb][Ee]-[Nn][Ll]|[Ss][Gg][Nn]-[Cc][Hh]-[Dd][Ee]' 
valueChars = '(?:%[\dA-F][\dA-F]|[-!#$&+.\dA-Z^-z|~])*' 
dispositionParm = '[Ff][Ii][Ll][Ee][Nn][Aa][Mm][Ee]\s*=\s*(?:({token})|"((?:{qdtext}|\\\\[\t !-~])*)")|[Ff][Ii][Ll][Ee][Nn][Aa][Mm][Ee]\*\s*=\s*({mimeCharset})\'(?:{language})?\'({valueChars})|{token}\s*=\s*(?:{token}|"(?:{qdtext}|\\\\[\t !-~])*")|{token}\*\s*=\s*{mimeCharset}\'(?:{language})?\'{valueChars}'.format(**locals()) 

try: 
    m = re.match('(?:{token}\s*;\s*)?(?:{dispositionParm})(?:\s*;\s*(?:{dispositionParm}))*|{token}'.format(**locals()), result.headers['Content-Disposition']) 

except KeyError: 
    name = path.basename(urllib.unquote(urlparse(url).path)) 

else: 
    if not m: 
    name = path.basename(urllib.unquote(urlparse(url).path)) 

    # Many user agent implementations predating this specification do not 
    # understand the "filename*" parameter. Therefore, when both "filename" 
    # and "filename*" are present in a single header field value, recipients 
    # SHOULD pick "filename*" and ignore "filename" 

    elif m.group(8) is not None: 
    name = urllib.unquote(m.group(8)).decode(m.group(7)) 

    elif m.group(4) is not None: 
    name = urllib.unquote(m.group(4)).decode(m.group(3)) 

    elif m.group(6) is not None: 
    name = re.sub('\\\\(.)', '\1', m.group(6)) 

    elif m.group(5) is not None: 
    name = m.group(5) 

    elif m.group(2) is not None: 
    name = re.sub('\\\\(.)', '\1', m.group(2)) 

    else: 
    name = m.group(1) 

    # Recipients MUST NOT be able to write into any location other than one to 
    # which they are specifically entitled 

    if name: 
    name = path.basename(name) 

    else: 
    name = path.basename(urllib.unquote(urlparse(url).path)) 
+0

वैकल्पिक रूप से नियमित रूप से अभिव्यक्तियों को भाषा टैग को मान्य न करके सरल अभिव्यक्ति को सरल बनाया जा सकता है, खासकर जब इसे अनदेखा किया जाता है। भाषा टैग में केवल असीमित संख्या में हाइफ़न, संख्याएं और अक्षर हो सकते हैं, और यह वैकल्पिक है। तो बस स्वीकार करें [- \ dA-Za-z] * dispositionParm = '[एफएफ] [आईआई] [एलएल] [ईई] [एनएन] [एए] [एमएम] [ईई] \ एस * = \ एस * (?: ({} टोकन) | "((?: {qdtext} | \\\\ [\ t! - ~]) *) ") | [एफएफ] [आईआई] [एलएल] [ईई] [एनएन] [एए] [एमएम] [ईई] \ * \ एस * = \ s * ({mimeCharset}) \ '[- \ dA-Za-z] * \' ({valueChars}) | {टोकन} \ s * = \ s * (: {टोकन} | "(? : {qdtext} | \\\\ [\ t! - ~]) * ") | {टोकन} \ * \ s * = \ s * {mimeCharset} \ '[- \ dA-Za-z] * \' {valueChars} 'प्रारूप (** स्थानीय()) – user916968

संबंधित मुद्दे