per CGI Datei zum Download anbieten...

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich möchte eigentlich nur eine Datei per CGI zum Download anbieten... Die schnellste Möglichkeit dazu ist einfach ein print "Location: "+DateiName+"\n\n" zu machen.
Das dumme ist nur, das der Dateiname gleich dem CGI-Skript ist...

Eine andere Möglichkeit sollte eigentlich folgende sein:

Code: Alles auswählen

#!/usr/bin/python

DateiName = "Beispiel.pdf"

print "Content-type: application/octet-stream\n"
print "Content-Disposition: filename="+DateiName+"\n\n"

f = open(DateiName, "rb")
print f.read()
f.close()
Jetzt sollte der Dateiname eigentlich "Beispiel.pdf" lauten... Tut's bei mir leider nicht :(

Jemand eine Idee warum???
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Oh... Wenn ich nur den Content-Disposition angebe, dann scheint es zu gehen...

Was aber auch nicht schlecht wäre, ist die Dateigröße (Content-length) mit anzugeben... Das funktioniert aber leider auch noch nicht so richtig...

In einigen Perl/PHP skripten wird auch oft ein binmode(STDOUT); gemacht...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

jens hat geschrieben:In einigen Perl/PHP skripten wird auch oft ein binmode(STDOUT); gemacht...
Das ist nur unter Windows nötig und eigentlich auch nur für Binärdateien: http://python.sandtner.org/viewtopic.php?t=2327
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
AFisch
User
Beiträge: 2
Registriert: Montag 1. November 2004, 11:01
Wohnort: Bamberg
Kontaktdaten:

Das Problem hatte ich auch schon. Nur der IE stellt sich an wie die Kuh beim .....

Mit diesen Headern sollte es klappen.
Cache-Control: must-revalidate
Content-Length: $filesize
Content-Disposition: attachment; filename=$file_name
Content-Transfer-Encoding: binary
Content-type: application/pdf [oder eben] Content-Type: application/octet-stream
Gruß AFisch
Nicht das Erreichte zählt, sondern das Erzählte reicht! (Politikerweisheit)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ach ich idiot :oops: Ich hab immer aus den PHP/Perl Beispielen die ganzen "/n" übernommen... Dabei erzeugt ja jeder print schon ein "/n", somit ist nur beim letzten eins Nötig...

Also so geht's:

Code: Alles auswählen

#!/usr/bin/python

import os

FileName = "../PDFs/Beispiel.pdf"

FileSize = os.path.getsize( FileName )

print 'Cache-Control: no-cache, must-revalidate'
print 'Pragma: no-cache'
print 'Content-Length: ' + str(FileSize)
print 'Content-Disposition: attachment; filename=' + os.path.basename( FileName )
print 'Content-Transfer-Encoding: binary'
print 'Content-Type: application/octet-stream\n'

f = open( FileName , "rb" )
print f.read()
f.close()
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

print find ich allgemein strange, das ist sogar ein Schlüsselwort! sys.stdout.write() ist logischer.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich frage mich gerade wie es bei sehr großen Dateien ist... Wird erst die ganze Datei in den Hauptspeicher gelesen oder nicht?

Ist das schon eine PIPE wenn man print f.read() macht?
BlackJack

Nein das ist keine Pipe. Erst wird das read() ausgefühert -- ganze Datei lesen -- dann wird das per print nach sys.stdout geschickt. Also ISO-Images sollte man auf diese Weise nicht downloaden. ;-)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hmmm... OK, da wir gerade dabei sind... Wie bekommen wir das hin, das auch ISO Images funktionieren...

Ich hab gesehen, das file() auch ein "bufzize" als Angabe hat, weiß aber nicht welche Funktion es genau hat:
file( filename[, mode[, bufsize]])
s. http://www.python.org/doc/lib/built-in- ... tml#l2h-25


Wie geht's also?
BlackJack

Du wirst die Dateien in einer Schleife selbst kopieren müssen. Bei file.read() kann man auch angeben wieviele Bytes gelesen werden sollen. Ungetestet:

Code: Alles auswählen

while True:
    data = f.read(8192)
    if not data:
        break
    sys.stdout.write(data)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Super, danke!
Antworten