2009-10-28 3 views

Répondre

19

Il n'y a pas besoin de bobince fait et tomber à httplib. Vous pouvez faire tout cela avec urllib directement:

>>> import urllib2 
>>> f = urllib2.urlopen("http://dalkescientific.com") 
>>> f.headers.items() 
[('content-length', '7535'), ('accept-ranges', 'bytes'), ('server', 'Apache/2.2.14'), 
('last-modified', 'Sun, 09 Mar 2008 00:27:43 GMT'), ('connection', 'close'), 
('etag', '"19fa87-1d6f-447f627da7dc0"'), ('date', 'Wed, 28 Oct 2009 19:59:10 GMT'), 
('content-type', 'text/html')] 
>>> f.headers["Content-Length"] 
'7535' 
>>> 

Si vous utilisez httplib alors vous pourriez avoir à implémenter la gestion de redirection, le support de proxy, et les autres belles choses qu'urllib2 fait pour vous.

1

vous pouvez vérifier la longueur du contenu dans une requête HEAD en premier lieu, mais attention, cet en-tête ne doit pas être réglé - voir How do you send a HEAD HTTP request in Python 2?

+0

Comment puis-je vérifier la longueur du contenu dans la requête HEAD? Est-ce considéré comme le téléchargement des en-têtes? – TIMEX

+0

Faire une demande HEAD est au mieux théorique si vous voulez utiliser urllib/urllib2. Ces modules prennent uniquement en charge les requêtes GET et POST. –

7

On pourrait dire:

maxlength= 12*1024*1024 
thefile= urllib2.urlopen(request).read(maxlength+1) 
if len(thefile)==maxlength+1: 
    raise ThrowToysOutOfPramException() 

mais bien sûr vous avez encore lu 12 Mo de données indésirables. Si vous voulez minimiser le risque que cela se produise, vous pouvez vérifier l'en-tête HTTP Content-Length, s'il est présent (il se peut que ce ne soit pas le cas). Mais pour ce faire, vous devez descendre à httplib au lieu de l'urllib plus général.

u= urlparse.urlparse(ep_url) 
cn= httplib.HTTPConnection(u.netloc) 
cn.request('GET', u.path, headers= {'User-Agent': ua}) 
r= cn.getresponse() 

try: 
    l= int(r.getheader('Content-Length', '0')) 
except ValueError: 
    l= 0 
if l>maxlength: 
    raise IAmCrossException() 

thefile= r.read(maxlength+1) 
if len(thefile)==maxlength+1: 
    raise IAmStillCrossException() 

Vous pouvez vérifier la longueur avant de demander l'obtention du fichier, si vous préférez. Ceci est fondamentalement le même que ci-dessus, sauf en utilisant la méthode 'HEAD' au lieu de 'GET'.

+0

merci beaucoup. ssdf – TIMEX

+1

Ceci est une meilleure solution, Content-Length n'étant pas fiable (Quelqu'un peut le définir incorrectement) –

+0

Solution parfaite - devrait être acceptée! –

1

Cela fonctionne si l'en-tête Content-Length est réglé

import urllib2   
req = urllib2.urlopen("http://example.com/file.zip") 
total_size = int(req.info().getheader('Content-Length')) 
+0

vous n'avez pas besoin de '.strip()': 1. 'getheader()' renvoie déjà la version 2 supprimée. 'Int()' ne se soucie pas des espaces avant/arrière. – jfs

+0

De même, il est inutile d'utiliser 'int (info(). Getheader())' si vous ne définissez pas la valeur par défaut: 'ValueError' de' int' est moins approprié que 'KeyError' de' req.headers '(note:' req.info() est req.headers') – jfs

+0

@Gourneau - Cela fonctionnerait-il encore si l'URL spécifiée est ftp: // url? –

Questions connexes