File-Upload mit CGI die zweite

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
ponder.stibbons
User
Beiträge: 9
Registriert: Montag 17. Februar 2003, 08:55
Kontaktdaten:

Montag 24. Februar 2003, 20:09

mit grossen interesse habe ich "milans" CGI-frage verfolgt.

ich stehe nun vor folgendem problem:
wenn ich eine jpeg-datei über multipart-formdata hochlade um sie unter anderem namen zu speichern - WIE bei behemoth stelle ich das an?

zu fuss im interaktiven input habe ich das schonmal hingekriegt:
eine datei binär zu öffnen, auszulesen und in eine andere datei binär reinzuschreiben.

lade ich sie hoch, bekomme ich auch ein fileobjekt, lasse ich es mir anzeigen, kann man mit 'n bischen glück sogar sehen, aus welcher digitalkamera es kommt bzw. durch welches bildbearbeitungsprogramm sie gelaufen ist.
die geschriebene datei ist aber nur 2-3 k gross.
:x
dabei kommt es nicht drauf an, ob das jpg 32 kB oder 1,5 MB hat!

kann/muss/sollte ich eine sowas wie puffergrösse o.ä. angeben?

hier mal der (ausgeräumte) code, oFile enthält das file-objekt aus cgi.FieldStorage():
---------schnipp--------------------------------------------------------

Code: Alles auswählen

def handleUpload(oFile):
	sStorefilename = 'dummy.jpg'
	oInput = oFile.file
	oTempfile = open(sStorefilename,'wb')
	tempInhalt = 'foo'
	while len(tempInhalt) != 0:
		tempInhalt = oInput.read()
		oTempfile.write(tempInhalt)
    
	oTempfile.close()
	return sStorefilename
---------schnapp--------------------------------------------------------
soweit so gut. fehlermeldungen kommen nicht.
das ganze läuft mit python 2.1.3 und dem xitami-webserver.
mit ascii-dateien klappt das ganz gut.
gibt es eine art EndOfFile-flag?
stört sich das script an nullen im hochgeladenen file?
ich habe hier schon mein halbes mobiliar zusammengetreten!

verzweifelte grüsse
ponder
Lieber Gott! Bitte hilf mir, mein dummes Maul zu halten, jedenfalls solange, bis ich WEISS wovon ich rede. Amen
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Montag 24. Februar 2003, 21:06

:D löl, gleiches Prob wie ich es anfangs hatte. Komischerweise muss man die Datei, in die man schreiben will im Asciimouds öffnen, auch wenn die Datei binär hochgeladen wird. Schreib also statt

Code: Alles auswählen

oTempfile = open(sStorefilename,'wb')
einfach das:

Code: Alles auswählen

oTempfile = open(sStorefilename,'w')
Dann dürfte es gehen. Mein Prob mit dem Upload hab ich bereits alles gelöst, läuft sowohl über FTP-Weiterleitung als auch über "normales" abspeichern der Daten.
Gast

Montag 24. Februar 2003, 23:28

nope - 3010 bytes
:-(
bissindietischkante
Gast

Montag 24. Februar 2003, 23:32

mit ascii (.txt) klapperts
word-dateien sehen nachher echt lustig aus

by the way: SOLLTE es mir gelingen, das ding zu übertragen und eventuell vernünftig auszulesen, habe ich auch schon eine idee, wie man determinieren kann, ob es eine ascii oder binärdatei ist.
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 25. Februar 2003, 08:41

also bei mir klappts... k.A. warums es bei dir nicht geht, hier mal der bei mir für's speichern zuständige teil des Scriptes: (file entsprichte deinem oFile, d.h. file.file ist dann dein oInput)

Code: Alles auswählen

f=open(dateiname,'w')
chunk=file.file.read(1024)
while chunk:
    f.write(chunk)
    chunk=file.file.read(1024)
f.close()
Bei mir funktionert das mit mp3, jpg Textdatein und allem anderem, deswegen wunderts mich, dass es bei dir nicht geht...
Zuletzt geändert von Milan am Dienstag 25. Februar 2003, 17:52, insgesamt 1-mal geändert.
Gast

Dienstag 25. Februar 2003, 17:20

bei asciidateien klappt das genauso wie bei meinem originalscript.
mit jpg genausowenig :-(

die GESCHRIEBENEN dateien variieren in der dateigrösse um ein paar bytes, WENN ICH DIESELBE DATEI mehrmals durchschicke.

ich argwöhne so langsam, dass der fehler beim AUSLESEN bereits auftritt.

irgendwann bekommt der gelesene chunk wohl den wert 0 oder die grösse 0 und das bedeutet in dieser codierung das ende der datei.

wenn ich das objekt mit dir(oFile) untersuche bekomme ich:

Code: Alles auswählen

FieldStorage('eineDatei', 'frohes_neues.jpg', '\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x02\x01\x00H\x00H\x00\x00\xff\xed\r0Photoshop 3.0\x008BIM\x03 ...jede menge binärmüll  ... \xdd')
jedenfalls WENIGER, als die datei GROSS ist :-(
gibt es kein vernünftiges EOF (end of file) in python bzw. für das FieldStorage-Objekt?

ich habe bis jetzt IMMER mit dieser krücke ganz gut gelebt...

ach ja - arbeitest du mit windows? (w2k, xitami, python 2.1.3)
ist MEINE python-version vielleicht irgendwie buggy?
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dienstag 25. Februar 2003, 18:02

zu hause arbeite ich mit windows, aufm Server auf dem das ganze ankommt ist unix. Ich hab gerade einen kleinen Fehler weggemacht, bei mir wurde jetzt in jedem Durchlauf die Datei geschlossen (ich hatte oben f.close() falsch eingerückt). Probiers damit nochmal. und füg mal bei dir im Code ganz oben das ein:

Code: Alles auswählen

import cgitb;cgitb.enable()
das sagt dem CGI-Script, falls ein fehler auftritt soll er gefangen werden und angezeigt werden, statt das Script zu beenden. Möglicherweise "verschweigt" dein Server ja deshalb bis jetzt nen Fehler.

Bei mir läuft mit dem Upload wie gesagt alles ok, siehe hier. Ich rate dir aber aus eigenem Interesse das nicht zu benutzen, weil im Moment alle Daten mitgeloggt werden, wenn das Powerpasswort falsch eingegeben wird (dann bekomm ich mit, ob jemand das Script von mir unberechtigt benutzt). ich geb dir mal meinen anderen Code, mit dem es bei mir funktioniert (ist ziemlich wuselig, hab ich gabastelt, als ich mit Python angefangen hab):

Code: Alles auswählen

#!/usr/bin/python
import cgitb; cgitb.enable()
import cgi,os

path= ""
path_absolut=0

einheit=1024        #Umrechnungszahl von Byte zur Einheit von maxsize, muss ungleich 0 sein.
#1=Byte; 1024=KByte; 1024*1024=MByte...
maxsize= 512         #Maximalgröße in einheit. Wenn maxsize=0, wird maxsize ignoriert. Muss ganzzahlig sein.
endung_erlaubt = [] #wenn leer, alle Endungen erlaubt, bis auf endung_verboten
                    #wenn nicht leer, nur diese Endungen erlaubt --> endung_verboten wird ignoriert, da alles andere verboten
endung_verboten = ['.cgi','.pl','.php','.php2','.php3','.php4']
                    #wenn auch leer, alle endungen erlaubt
#aber in beiden Listen dürfen nicht die selben Endungen stehen, da sie sonst erlaubt UND verboten sind

print "Content-type: text/html\n\n"
form=cgi.FieldStorage()
if form.value==[]:
    print """<html>
<head>
<title>Uploadtest</title>
</head>
<body>
<form method="POST" action="save.pl" ENCTYPE="multipart/form-data">
<input name="datei" type="file" size="33">
<input name="with_check" type="submit" value="Upload (Abfrage ob vorhanden)">
<input name="without_check" type="submit" value="Upload / Delete">
</form>
</body>
</html>"""

#Begin der anderen Abfragen
elif form["datei"].file and form["datei"].value:
    file=form["datei"]
    dateiname=os.path.basename(file.filename.replace('\\',os.sep).replace('/',os.sep))
    endung=os.path.splitext(dateiname)[1].lower()
    size=long(len(file.value))
    g,k=divmod(size,einheit)
    einheitname=["","K","M","G","T"][einheit/1024]
#überprüfung von endung_erlaubt:
    if endung_erlaubt and not (endung in endung_erlaubt):
        print "Die Datei ist nicht in der Liste der erlaubten Dateitypen. Es wurde nicht gespeichert."
        print "Folgende Dateitypen sind erlaubt:\n"
        for i in endung_erlaubt:
            print "\t%s"%i
#überprüfung von endung_verboten:
    elif endung_verboten and endung in endung_verboten:
        print "Die Datei ist ein verbotener Dateityp. Es wurde nicht gespeichert."
        print "Folgende Dateitypen sind verboten:\n"
        for i in endung_verboten:
            print "\t%s"%i
#überprüfen der Dateigröße
    elif maxsize and ((g >= maxsize and k > 0) or (g > maxsize)):
        print "Die Maximalgröße wurde überschritten; die Datei wurde nicht gespeichert...\nEs sind maximal %i %sByte erlaubt."%(maxsize,einheitname)
#Speichervorgang:
    else:
        aktuell=os.getcwd()
        if not path_absolut:
            aktuell=os.path.join(aktuell,path)
        os.chdir(aktuell)
#testen, ob Datei vorhanden ist
        vorhanden=os.path.exists(dateiname)
        if vorhanden and (form.has_key("with_check")):
            print 'Die Datei gibt es schon... es wurde nicht gespeichert.'
        else:
            f=open(dateiname,'w')
            chunk=file.file.read(1024)
            while chunk:
                f.write(chunk)
                chunk=file.file.read(1024)
            f.close()
            print "Datei gespeichert"
else:
    print "Datei existiert nicht oder keine Datei ausgewählt"
ponder.stibbons
User
Beiträge: 9
Registriert: Montag 17. Februar 2003, 08:55
Kontaktdaten:

Mittwoch 26. Februar 2003, 11:19

aaaalso - ich habe jetzt ALLES ausprobiert, inklusive einer neuen pythonversion.
ich habe mit 'ner zählschleife versucht zu erzwingen, dass mein script 22321 mal ein byte aus der gesendeten datei liest.
das ergebnis ist immer wieder dasselbe:
ein 6+ mb grosser ascii-text wird komplett übertragen, ein gif von 808 bytes geht verloren...

auch mit DEINEM skript - also liegt der fehler wohl in meiner kombination von windows/webserver/python...

wie gesagt - ich entwickle und teste lokal über http.


darf ich dir mal ein jpg an deinem link hochladen?
genau 102.452 bytes...
und du sagst mir, vieviel davon bei dir ankommt?

thx
anDee
Lieber Gott! Bitte hilf mir, mein dummes Maul zu halten, jedenfalls solange, bis ich WEISS wovon ich rede. Amen
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Mittwoch 26. Februar 2003, 12:58

lad mal hier hoch. Die Dateigröße ist auf 512 Kbytes begrenzt, kann mal machen. Muss aber Funktionieren, weil ich das schon mit allem möglichem gemacht habe. Tu aber bitte mal den gefallen und nimm als deteinamen deinen Usernamen, damit ich das dann weiß, dass das von dir ist.
ponder.stibbons
User
Beiträge: 9
Registriert: Montag 17. Februar 2003, 08:55
Kontaktdaten:

Mittwoch 26. Februar 2003, 16:03

so, habe dir genau 102.452 bytes geschickt.
"ponder_stibbons.jpg"
thx

(just curious: wieso endet die cgi-datei auf ".pl"?)
Lieber Gott! Bitte hilf mir, mein dummes Maul zu halten, jedenfalls solange, bis ich WEISS wovon ich rede. Amen
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Mittwoch 26. Februar 2003, 18:00

Ich vermute mal das Milan zu faul (oder so :roll: ) war .py oder .cgi Dateien in den CGI-ActionHandler einzufügen, habbich recht?

Und ponder.stibbons, ich finde ja einige Signaturen witzig, und schreibe selber Emails mit Sinnsprüchen drunter, aber deine finde ich geschmacklos... (Nimms nich persönlich, aber das wollte ich mal loswerden)
mfg,

10011110
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Mittwoch 26. Februar 2003, 18:02

http://www.pythonarea.net/max/Upload/da ... ibbons.jpg ist vollständig da... es muss also an deinem Server liegen, denn der Code vom meinem Script steht 1:1 oben und du hast ihn schon probiert. ( Ich lösch die Datei übermorgen wieder, so dass du es dir vorher angucken kannst)

Das die Datei die Endung pl hat liegt an puretec, die haben ihre CGI-Scripte so eingestellt und schlagen somit gleich zwei Fliegen zum Nachteil von Python: die Datei wird als CGI erkannt (Pearlendung) aber in der ersten Zeile steht erst der Pfad des Interpreters...
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Mittwoch 26. Februar 2003, 18:04

ASCII158 hat geschrieben:Ich vermute mal das Milan zu faul (oder so :roll: ) war .py oder .cgi Dateien in den CGI-ActionHandler einzufügen, habbich recht?
der Server/account gehört auch net mir, deswegen bin ich wirklich zu "faul" dran rumzufummeln, weil ich keine Einstellungen verändern will. Ich darf den Account nur mitbenutzen.
ponder.stibbons
User
Beiträge: 9
Registriert: Montag 17. Februar 2003, 08:55
Kontaktdaten:

Mittwoch 26. Februar 2003, 19:51

ASCII158 hat geschrieben:finde ich geschmacklos... (Nimms nich persönlich, aber das wollte ich mal loswerden)
naja - bin eben seit dem 9. lebensjahr zyniker...
und TECHNISCH gesehen stimmts ja.

aber bevor ich hier rausfliege, schau ich mal, ob ich 'n besseren finde.

wie wär's mit:

Lieber Gott, gib mir Geduld...JETZT SOFORT!
Schwarze Löcher sind da, wo Gott durch Null geteilt hat.
Jesus Christus starb für Eure Sünden, also enttäuscht ihn nicht!
oder vielleicht besser
"that's entertainment" - vlad der pfähler
;-)

aber mal im ernst - kann mir jemand 'n tip geben, welchen kleinen webserver ich OHNE viel aufwand zuhause zum testen benutzen kann?
wer hat mit sowas erfahrung?
habe xitami genommen, weil der am schnellsten vom startblock weg ist...
Lieber Gott! Bitte hilf mir, mein dummes Maul zu halten, jedenfalls solange, bis ich WEISS wovon ich rede. Amen
RicmanX
User
Beiträge: 69
Registriert: Donnerstag 29. August 2002, 17:10
Wohnort: Erfurt
Kontaktdaten:

Mittwoch 26. Februar 2003, 20:01

@ASCII: Verrat mir mal wie ich .cgi per htaccess als ActionHandler hinzufüge.

.py geht ja, aber das erzeugt bytecode und deshalb verwenden wir es nur als module (da man auch nur diese importieren kann) und .pl halt zwangweise momentan für Scripte.
Antworten