per CGI Datei zum Download anbieten...

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

Donnerstag 27. Januar 2005, 19:29

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
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 27. Januar 2005, 19:41

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
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 27. Januar 2005, 21:08

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 Modvoice
AFisch
User
Beiträge: 2
Registriert: Montag 1. November 2004, 11:01
Wohnort: Bamberg
Kontaktdaten:

Donnerstag 27. Januar 2005, 22:00

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
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 28. Januar 2005, 09:28

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
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 28. Januar 2005, 13:31

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 Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 10. Februar 2005, 08:37

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

Donnerstag 10. Februar 2005, 16:59

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
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 11. Februar 2005, 07:40

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

Samstag 12. Februar 2005, 00:17

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
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 14. Februar 2005, 08:20

Super, danke!
Antworten