Seite 1 von 1

per CGI Datei zum Download anbieten...

Verfasst: Donnerstag 27. Januar 2005, 19:29
von jens
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???

Verfasst: Donnerstag 27. Januar 2005, 19:41
von jens
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...

Verfasst: Donnerstag 27. Januar 2005, 21:08
von Leonidas
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

Verfasst: Donnerstag 27. Januar 2005, 22:00
von AFisch
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

Verfasst: Freitag 28. Januar 2005, 09:28
von jens
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()

Verfasst: Freitag 28. Januar 2005, 13:31
von Leonidas
print find ich allgemein strange, das ist sogar ein Schlüsselwort! sys.stdout.write() ist logischer.

Verfasst: Donnerstag 10. Februar 2005, 08:37
von jens
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?

Verfasst: Donnerstag 10. Februar 2005, 16:59
von 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. ;-)

Verfasst: Freitag 11. Februar 2005, 07:40
von jens
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?

Verfasst: Samstag 12. Februar 2005, 00:17
von 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)

Verfasst: Montag 14. Februar 2005, 08:20
von jens
Super, danke!