2010-08-20 5 views
6

zum Download Ich versuche, eine Zip-Datei mit diesem Code zum Download:Python: Wie eine Zip-Datei

o = urllib2.build_opener(urllib2.HTTPCookieProcessor()) 

#login 
p = urllib.urlencode({ usernameField: usernameVal, passField: passVal }) 
f = o.open(authUrl, p) 
data = f.read() 
print data 
f.close() 

#download file 
f = o.open(remoteFileUrl) 
localFile = open(localFile, "wb") 
localFile.write(f.read()) 
f.close() 

ich einige binären Daten immer bin, aber die Größe der Datei I „heruntergeladen“ ist zu klein und keine gültige Zip-Datei. Erhalte ich die Zip-Datei nicht richtig? Der HTTP-Antwortheader für f = o.open(remoteFileUrl) wird unten angezeigt. Ich weiß nicht, ob eine spezielle Verarbeitung benötigt wird, diese Antwort zu handhaben:

HTTP/1.1 200 OK Server:
Apache-Coyote/1.1 Pragma: privat
Cache-Control: Must-revalidate
Verfällt : Di, 31 Dez 1997 23:59:59 GMT
Inhalt-Disposition: Inline;
filename = "files.zip";
Content-Type: application/zip
Transfer-Encoding:

chunked

Antwort

10

f.read() nicht unbedingt die gesamte Datei lesen, aber nur ein Paket davon (die die gesamte Datei sein könnten, wenn es klein ist, aber wird nicht für eine große Datei sein).

Sie müssen Schleife über die Pakete wie folgt aus:

while 1: 
    packet = f.read() 
    if not packet: 
     break 
    localFile.write(packet) 
f.close() 

f.read() ein leeres Paket zurück, um anzuzeigen, dass Sie die gesamte Datei gelesen haben.

+2

würde ich gespannt sein, wo in der Dokumentation, die Sie gefunden –

+0

http://docs.python.org/library/urllib.html#urllib.urlopen: "ein dateiähnliches Objekt wird zurückgegeben" dann http://docs.python.org/library/stdtypes.html#file .read – RichieHindle

+0

wirklich nur ein Paket? Ich überprüfte die Dokumente an der Verbindung, die gezeigt wird und nicht irgendwo sehen, dass es sagt, dass read() nicht bis EOF liest. Kannst du mehr erklären? –

1

Wenn Sie nichts dagegen haben die gesamte Zip-Datei in den Speicher zu lesen, der schnellste Weg, um es zu lesen und zu schreiben ist wie folgt:

data = f.readlines() 
with open(localFile,'wb') as output: 
    output.writelines(data) 

Ansonsten in Stücke zu lesen und schreiben, wie Sie sie bekommen über das Netzwerk, tun

with open(localFile, "wb") as output: 
    chunk = f.read() 
    while chunk: 
     output.write(chunk) 
     chunk = f.read() 

Dies ist ein wenig weniger sauber, aber vermeidet die ganze Datei im Speicher auf einmal zu halten. Ich hoffe es hilft.

0

Try this:

#download file 
f = o.open(remoteFileUrl) 

response = "" 
while 1: 
    data = f.read() 
    if not data: 
     break 
    response += data 

with open(localFile, "wb") as local_file: 
    local_file.write(response) 
1

Hier ist eine robustere Lösung urllib2 mit der Datei in Stücke zum Download und den Status des Download drucken

import os 
import urllib2 
import math 

def downloadChunks(url): 
    """Helper to download large files 
     the only arg is a url 
     this file will go to a temp directory 
     the file will also be downloaded 
     in chunks and print out how much remains 
    """ 

    baseFile = os.path.basename(url) 

    #move the file to a more uniq path 
    os.umask(0002) 
    temp_path = "/tmp/" 
    try: 
     file = os.path.join(temp_path,baseFile) 

     req = urllib2.urlopen(url) 
     total_size = int(req.info().getheader('Content-Length').strip()) 
     downloaded = 0 
     CHUNK = 256 * 10240 
     with open(file, 'wb') as fp: 
      while True: 
       chunk = req.read(CHUNK) 
       downloaded += len(chunk) 
       print math.floor((downloaded/total_size) * 100) 
       if not chunk: break 
       fp.write(chunk) 
    except urllib2.HTTPError, e: 
     print "HTTP Error:",e.code , url 
     return False 
    except urllib2.URLError, e: 
     print "URL Error:",e.reason , url 
     return False 

    return file 
+0

Es wird nur robust sein, wenn Sie den Fall behandeln, in dem keine Kopfzeile 'Content-Length' gesendet wird IMO –

+0

Guter Punkt Xavier – Gourneau