File-Upload mit CGI

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Ich experimentier gerade ein wenig mit dem Uploaden von Dateien über CGI und hab mal ein paar Fragen. Mittels cgi.Fieldstorage habe ich alles Werte eingesammelt und die zu speichernde Datei rausgeholt. Sie steckt als Fieldstorage-Objekt in der Variable file. Das wirkliche file-Objekt steckt allerdings in file.file. (hier mal zur verdeutlichung:)

Code: Alles auswählen

import cgi
formular=cgi.FieldStorage()
file=formular['datei'] #rausholen der Unterinstanz von FieldStorage, die alles zur Datei beinhaltet.
real_file=file.file #wirkliches Dateiobjekt
Wenn ich jetzt mal dir(file) mache kommt das raus:

Code: Alles auswählen

['FieldStorageClass', '_FieldStorage__file', '_FieldStorage__write', '__doc__', '__getattr__', '__getitem__', '__init__', '__len__', '__module__', '__repr__', 'bufsize', 'disposition', 'disposition_options', 'done', 'file', 'filename', 'fp', 'getfirst', 'getlist', 'getvalue', 'has_key', 'headers', 'innerboundary', 'keep_blank_values', 'keys', 'length', 'list', 'make_file', 'name', 'outerboundary', 'read_binary', 'read_lines', 'read_lines_to_eof', 'read_lines_to_outerboundary', 'read_multi', 'read_single', 'read_urlencoded', 'skip_lines', 'strict_parsing', 'type', 'type_options']
mich interessieren besonders read_binary, read_lines, read_lines_to_outerboundary. Was machen sie? Ich habe dazu keine Dokumentationen gefunden. Zwar kann ich mir denken das read_binary und read_lines zwischen Binär und Ascii-Lesemodus des wirklichen Filesobjektes wechseln, da sie beide None zurückgeben. Aber genau weiß ich es nicht. Und auch zu read_lines_to_outerboundary wüsste ich gerne mehr. Ich habe keine Vorstellung was es machen kann, würde aber gerne wenigstens mit den anderen beiden arbeiten, um Daten im Binär oder Ascii-Modus an FTP-Server weiterzuleiten.

real_file hat übrigens alle methoden wie ein wirkliches file-Objekt, des wegen müsste die Steuerung wohl logischerweise über file laufen. Kann mir jemand helfen?
Zuletzt geändert von Milan am Samstag 18. Januar 2003, 23:09, insgesamt 1-mal geändert.
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Ich hab' keine große Ahnung von cgi mit Python, fand aber Folgendes in der Library Reference unter 11.2.2 Using the cgi module:
If a field represents an uploaded file, accessing the value via the value attribute or the getvalue() method reads the entire file in memory as a string. This may not be what you want. You can test for an uploaded file by testing either the filename attribute or the file attribute. You can then read the data at leisure from the file attribute:

Code: Alles auswählen

fileitem = form["userfile"]
if fileitem.file:
    # It's an uploaded file; count lines
    linecount = 0
    while 1:
        line = fileitem.file.readline()
        if not line: break
        linecount = linecount + 1
Hilft das vielleicht weiter?
Jan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

hilft mir leider nicht wirklich, weil das nur beschreibt, wie ich Zeile für Zeile auslese. Das wäre ganz klar im Asciimodus. wenn ich aber z.B. read nehme, steht das nicht so eindeutig fest, ob die Daten binär oder ascii-weise gelesen werden. Deswegen sind für mich die Attribute der FieldStorage-Instanz so wichtig, von denen ich aber keine Doku gefunden habe... :(
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Die von Dir genannten Methoden sind alle nur für den internen Gebrauch. Damit würde ich nichts machen.
Aber Du hast ja auch keine Möglichkeit, zu ermitteln, ob da eine Text-(aka ASCII-) oder Binärdatei kommt. Der "Absender" kann ja nicht explizit angeben, was für eine Art Datei das ist (anders als bei FTP). Und programmatisch lässt sich der Unterschied eh nicht ermitteln, da die Frage, ob eine Datei eine Text- oder Binärdatei ja eher 'philosopischer' Natur ist.
Jan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Voges hat geschrieben:Der "Absender" kann ja nicht explizit angeben, was für eine Art Datei das ist (anders als bei FTP). Und programmatisch lässt sich der Unterschied eh nicht ermitteln, da die Frage, ob eine Datei eine Text- oder Binärdatei ja eher 'philosopischer' Natur ist.
Komischerweise ja, selbst wenn ich die Daten anschließend per FTP weiterleiten will. Ich hab mal ne Reihe von Tests gemacht und rausgefunden, dass man zwar mit storbinary und storlines binär und ascii-modus handhaben kann, aber das Python das völlig egal ist, was man von beiden nimmt. Wenn ich eine Binärdatei mit Python asciiweise uploade passiert genauso wenig, wie umgekehrt. Insofern hat sich das selbst erledigt. Trotzdem Danke. :roll:
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Milan hat geschrieben:Ich hab mal ne Reihe von Tests gemacht und rausgefunden, dass man zwar mit storbinary und storlines binär und ascii-modus handhaben kann, aber das Python das völlig egal ist, was man von beiden nimmt.
Das Verhalten ist in cgi.py aber auch dokumentiert:

Code: Alles auswählen

def make_file(self, binary=None):
   """
   ...
   The 'binary' argument is unused -- the file is always opened
   in binary mode.	
   ...
   """
   import tempfile
   return tempfile.TemporaryFile("w+b")
Jan

NACHTRAG: Sorry, ich sehe gerade, dass sich Deine Beobachtung auf FTP bezog.
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Code: Alles auswählen

filename = "test.dat"      # enthält "\r\n" also Zeilenumbrüche
ftp.storbinary("STOR " + filename + ".bin", open(filename, "rb"), 1024)
ftp.storlines("STOR " + filename + ".text", open(filename))
Also, wenn ich obiges mache, dann bleiben in der Datei "textdatei.bin" die Zeichensequenzen "\r\n" erhalten und in der Datei "textdatei.text" fehlen die "\r" (zumindest bei einem Unix-FTP-Server).
Das heißt, wenn Du in Deinem CGI-Script die Datei erhälst, sie vielleicht zwischenspeicherst, dann (wie auch immer) entscheidest, ob es eine Text- oder Binärdatei ist und dementprechend wie oben mit "storbinary()" oder "storlines()" weiterleitest, müsste das eigentlich klappen.
Jan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

schon gelöst das ganze... ich bin dann auch selber auf die Idee gekommen und hab einfach zwei Radiobutton für die Auswahl mit ausgeben lassen. Danke nochmal. :)
Antworten