Multiple FileUpload ohne file="type" möglich ???

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
leunam1985
User
Beiträge: 4
Registriert: Montag 26. Mai 2008, 15:39

Hallo,

ich weiß, dass Thema wurde schon oft genannt, jedoch habe ich für mein Problem noch keine Lösung in eurem Forum gefunden, daher hier einmal meine Frage:

Ist es möglich einen FileUpload zu machen ohne ein Input-Feld "type" ?
Ich arbeite mit TurboGears und Python 2.5 und habe dazu ein kid.template gebaut, welches mit Javascript eine art mehrfachuplod darstellen soll. Das geht dann so, dass es ein Input-Feld type="file" gibt und der User dort eine Datei auswählt und auf hinzufügen drückt. Jetzt wird kein submit gemacht, sondern über javascript die Datei in nem Hiddenfeld gespeichert und der User kann weitere Dateien hinzufügen (über das eine Input-Feld). Wenn er fertig ist, dann klickt er auf Uploaden und es wird ein submitted. Ich habe alles soweit hinbekommen, habe in der controller.py alle Dateien inkl. vollständigem Pfad usw. da, nur diese sind natürlich kein Objekt, also bekomme ich eine Fehlermeldung, wenn ich über

Code: Alles auswählen

aktFile.file.read()
darauf zurgreifen möchte, da dieses Objekt ja auch keine file-methode hat. Ich habe eine Schleife usw. und alles funktioniert wunderbar nur eben das auslesen der Dateien klappt nicht. Wenn ich versuche einen cast zu machen und schreibe... (aFiles[] ist die Liste der übergebenen Dateien)

Code: Alles auswählen

aktFile = file(aFiles[i])
total_data=""
while True:
  data = aktFile.file.read()
  if not data:
  break
total_data += data
legt er mir sogar die Dateien auf dem Server an, nur sind die hinterher nicht mehr zu gebraucht, egal ob Bild, Archiv oder pdf, es muss alles gehen.

Hier der Code meiner Upload-Funktion:

Code: Alles auswählen

def do_upload(self, **keywords):
		form_group_id = keywords['form_group_id']
		form_praktikum = keywords['form_praktikum']
		form_versuch = keywords['form_versuch']
		form_delivery_id = keywords['form_delivery_id']
		files_2_upload = keywords['files_2_upload']
		amount_files = keywords['amount_files']
		kommentar = keywords['kommentar']

		if (amount_files > 0):
			""" Trenne Dateien nach | """
			aFiles = files_2_upload.split("|")
			sAusgabe = ""

			""" Ueberpruefe Zielpfad und erstelle ggf. """
			if not os.path.exists(UPLOAD_DIR + "\\" + form_praktikum):
				os.makedirs(UPLOAD_DIR + "\\" + form_praktikum)
			if not os.path.exists(UPLOAD_DIR + "\\" + form_praktikum + "\\" + form_versuch):
				os.makedirs(UPLOAD_DIR + "\\" + form_praktikum + "\\" + form_versuch)
			
			""" Uebergebe Zielpfad """
			target_path = UPLOAD_DIR + "\\" + form_praktikum + "\\" + form_versuch
			
			""" Hole Timestamp """
			aktDateTime = datetime.datetime.now()
			sTimeStamp = aktDateTime.strftime("%Y%m%d%I%M%S_")

			for i in range(0,len(aFiles)-1):
				""" Filtere den Dateinamen raus """
				sFileName = sTimeStamp + aFiles[i][aFiles[i].rfind("\\")+1:len(aFiles[i])]

				sAusgabe = sAusgabe + "Files: %s <br>" % (sFileName)
				
""" ******* HIER BRAUCHE ICH EINE METHODE ZUM AUSLESEN EINER DATEI ******* >>>"""
				aktFile = file(aFiles[i])
				total_data=""
				while True:
					data = aktFile.file.read()
					if not data:
						break
					total_data += data

""" <<< ******* HIER BRAUCHE ICH EINE METHODE ZUM AUSLESEN EINER DATEI ******* """

				target_file_name = os.path.join(os.getcwd(), target_path, sFileName)
				
				""" open file in binary mode for writing """
				f = open(target_file_name, 'wb')
				f.write(total_data)
				f.close()
				
			return sAusgabe
Ich bin wirklich für jede Hilfe sehr dankbar, vielleicht habe ihr auch ein paar Ideen zu Work-Arounds, alles kann helfen.

Danke,
Lg Manu
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

def do_upload(self, **keywords):
        form_group_id = keywords['form_group_id']
        form_praktikum = keywords['form_praktikum']
        form_versuch = keywords['form_versuch']
        form_delivery_id = keywords['form_delivery_id']
        files_2_upload = keywords['files_2_upload']
        amount_files = keywords['amount_files']
        kommentar = keywords['kommentar'] 
WTF?

Und Pfade solltest du mit os.path.join joinen.

Code: Alles auswählen

            for i in range(0,len(aFiles)-1):
WTF?


Ich geh hier einfach weg, der Code schmerzt.
leunam1985
User
Beiträge: 4
Registriert: Montag 26. Mai 2008, 15:39

weiß ja, dass ich noch ein turbogears und python neuling bin, aber so brauchst du mir auch nicht gleich kommen.

Kannst du mir da nicht weiterhelfen?
lunar

my 2 cents:

Grundsätzlich sind tripple-quoted-strings kein Kommentarersatz, dafür gibt es in Python die Raute (#). Und die Ungarische Notation für Namen ist in Python doch sehr deplaziert.

Ferner nutzt man ``os.path.join``, um Pfade zusammenzusetzen, du solltest Zeile wie Z. 18 also dementsprechend anpassen.

An ``for i in range(0,len(aFiles)-1):`` ist so ziemlich alles falsch, was man falsch machen kann. Zuallerst mal sollte man ``xrange`` nutzen, wenn man die Liste nicht braucht, sondern nur am fortlaufenden Zähler interessiert ist. Desweiteren kann man das erste Argument auch weglassen, da ``range`` und ``xrange`` automatisch bei 0 anfangen, wenn nur ein Argument übergeben wurde. Dann stellt sich die Frage, ob es wirklich beabsichtigt ist, dass letzte Element der Liste auszulassen, ``range`` und ``xrange`` definieren das Zahl-Intervall nämlich als ``[a,b[``. Das zusammengenommen, kommt man auf ``for i in xrange(len(aFiles))``.

Allerdings ist auch das nicht die beste Art und Weise, über Listen zu iterieren, da Listen selbst "iterable" sind: ``for element in aFiles:``. Wenn du den Index benötigst, dann nimm ``enumerate``.

In Zeile 31 versucht du, den Dateinamen mittels Slicing herauszuschneiden. Dafür sind die entsprechenden Funktionen aus dem Modul ``os.path`` allerdings besser geeignet.

In der Schleife in Zeile 38 ff. nutzt du String-Konkatenation. Da Zeichenketten in Python unveränderbar sind, muss dazu jedes Mal ein neues String-Objekt erstellt und der Speicher des alten kopiert werden. Effizienter ist es daher, die Teilstücke in einer Liste zu sammeln und am Ende ``join`` zu nutzen: ``''.join(parts)``.

Dateien sollte man nicht ohne entsprechende Ausnahmebehandlung – entweder mit dem ``with``-Statement oder über ein ``try``-``finally``-Konstrukt – öffnen.

Das wäre erstmal die grundlegenden "Mängel" im Code.

Zu deinem eigentlichen Problem: Du möchtest per Java-Script Daten auf einen Server hochladen, ohne entsprechende ``input``-Felder zu verwenden. Sehe ich das richtig? Warum nur sendest du dann die Dateinamen? Du solltest doch vielmehr einen Post-Request schicken, der die Dateien enthält. Den kannst du dann mit entsprechenden Feldnamen versehen, beispielsweise mit fortlaufendem Zähler: ``file1``, ``file2``, usw.

Nichts für ungut, aber ich habe alles in allem das Gefühl, dass du weder von HTTP noch von Python sonderlich viel Ahnung hast. In diesem Fall ist es dann auch ein wenig früh, um solche Webanwendungen zu schreiben, du solltest lieber erstmal Python einigermaßen beherrschen, in dem du das Tutorial durcharbeitest, ein entsprechendes Buch liest (A Byte Of Python beispielsweise), Übungsaufgaben implementierst. Dann kannst du dich in HTTP einlesen und deine Webanwendung implementieren. So ganz ohne Vorwissen ist der Versuch imho zum Scheitern verurteilt. Wie gesagt, nichts für ungut, dass ist meine persönliche Meinung ;)

@audax
Das Niveau des eigenen Postings sollte sich vielleicht nicht unbedingt am Niveau des geposteten Codes orientieren. Soll heißen, wenn dir nicht mehr einfällt als "WTF", dann poste lieber gar nicht :roll:
leunam1985
User
Beiträge: 4
Registriert: Montag 26. Mai 2008, 15:39

Danke für deine Hilfe sowohl was die Programmierung angeht, als auch bei der Sache mit "audax"...solche User sollten echt einfach die Klappe halten, bevor sie solch unqualifizierte Kommentare von sich geben.

Die Hinweise bzgl. meines Codes habe ich bereits eingebaut, super Hilfe! Allerdings bin ich nicht ganz unerfahren was das Programmieren angeht, halt nur noch ein Neuling was Python angeht. Meine Schiene ist mehr die C, C++ und C# Richtung. Habe früher mit ASP und PHP viel Webanwendungen entwickelt, daher ist mir schon klar, dass es am einfachsten wäre, dass ich einen type="file" für jede Datei erstelle, diese dann via Post an die controller schicke und verarbeite. Aber gerade das möchte ich nicht, wenn es nicht auch irgendwie anders geht.

Ich verwende auf der vorigen Seite nur Javascript um Client-seitig eine schönere Ansicht hinzubekommen und habe ein Hidden-Feld, welcher die Dateinamen der einzelnen Dateien speichert. Ich möchte eben nicht 5, 6 oder mehr input-felder mit den type="file", sondern habe eben nur eins, dennoch soll es möglich sein mehrere Dateien hochzuladen. Meine Frage war also eher, kann ich auch ohne Post-Request, die Dateien hochladen? Mit Text-Dateien funktioniert das wunderbar, lese die aus, erstelle eine neue Datei und schreibe sie wieder rein, aber eben nicht mit anderen. Gibt es dort keine Möglichkeit? Sonst müsste ich einen Workaround schreiben, der irgendwie jede Datei einzeln hochlädt oder einen zwischenseite wo eben soviele input-felder wie benötigt werden kreiert werden und dann via post abgesetzt werden.

Geht das wirklich nicht anders? Das war nur meine eigentliche Frage! Ich habe die Dateinamen der Files und will sie hochladen ohne sie über Post-Request zu schicken...
Kann man außer mit einem type="file" vielleicht noch auf anderem Weg die Dateien schicken ohne das diese auf der Client-Seite angezeigt werden, also so wie Hidden-Felder? Das wäre natürlich auch eine schöne Lösung.

Danke nochmal für deine Hilfe.
Lg und bis bald, Manu
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

leunam1985 hat geschrieben:Danke für deine Hilfe sowohl was die Programmierung angeht, als auch bei der Sache mit "audax"...solche User sollten echt einfach die Klappe halten, bevor sie solch unqualifizierte Kommentare von sich geben.
Vorsicht was du da sagst.
Habe früher mit ASP und PHP viel Webanwendungen entwickelt, daher ist mir schon klar, dass es am einfachsten wäre, dass ich einen type="file" für jede Datei erstelle, diese dann via Post an die controller schicke und verarbeite. Aber gerade das möchte ich nicht, wenn es nicht auch irgendwie anders geht.
Ich glaube das bekräftigt meine Meinung, dass man keine Webanwendungen entwickeln soll ohne HTTP Basics zu kennen. Was möglich ist und was nicht steht im RFC 2616. Und das ist Pflichtliteratur.
TUFKAB – the user formerly known as blackbird
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

leunam1985 hat geschrieben:Danke für deine Hilfe sowohl was die Programmierung angeht, als auch bei der Sache mit "audax"...solche User sollten echt einfach die Klappe halten, bevor sie solch unqualifizierte Kommentare von sich geben.
Das `unqualifiziert` verbitte ich mir. Und ich denke doch, dass manchmal ein `WTF` ausreicht, es war doch wirklich ersichtlich das ich damit nach den Gründen für solchen Code fragte.

Übrigens:
Ist es mir von deiner Seite aus erlaubt, den folgenden Code bei thedailywtf.com ins Forum zu stellen?

Code: Alles auswählen

def do_upload(self, **keywords):
        form_group_id = keywords['form_group_id']
        form_praktikum = keywords['form_praktikum']
        form_versuch = keywords['form_versuch']
        form_delivery_id = keywords['form_delivery_id']
        files_2_upload = keywords['files_2_upload']
        amount_files = keywords['amount_files']
        kommentar = keywords['kommentar']
Der hat einfach was :D
lunar

leunam1985 hat geschrieben:Danke [...] auch bei der Sache mit "audax"...solche User sollten echt einfach die Klappe halten, bevor sie solch unqualifizierte Kommentare von sich geben.
Was für audax gilt, gilt auch für dich. Ich hoffe, ich muss nicht bereuen, dir Schützenhilfe geleistet zu haben ...
leunam1985 hat geschrieben:Meine Schiene ist mehr die C, C++ und C# Richtung. Habe früher mit ASP und PHP viel Webanwendungen entwickelt
Nichts für ungut, aber das sehe ich nicht gerade als Qualifikation. C hat noch mit Python zu tun, aber C++, C#, ASP und PHP sind eine andere Welt. Python vor diesem Hintergrund ist wie ein Neuanfang, zumal die Paradigmen aus der ASP- und PHP-Programmierung in der Python-Welt verpönt, wenn nicht sogar verabscheut sind.
dass ich einen type="file" für jede Datei erstelle, diese dann via Post an die controller schicke und verarbeite. Aber gerade das möchte ich nicht, wenn es nicht auch irgendwie anders geht.
Wenn es kein Post-Request ausgehend von einem Webformular sein soll, wie willst du das dann anstellen? Den Post-Request könnte man afaik zur Not noch mit einem Javascript zusammenbauen, wobei ich allerdings auch darauf keine Garantie abgeben würde, ich habe nicht viel Ahnung von Javascript.

Allerdings wirst du dir schwertun, mittels Javascript den Inhalt einer lokalen Datei einfach so auszulesen, nicht umsonst implementieren moderne Browser eine Javascript-Sandbox. Alles andere würde ich auch als schwere Sicherheitslücke umgehend an die Entwickler des Browsers melden!
Ich möchte eben nicht 5, 6 oder mehr input-felder mit den type="file", sondern habe eben nur eins, dennoch soll es möglich sein mehrere Dateien hochzuladen. Meine Frage war also eher, kann ich auch ohne Post-Request, die Dateien hochladen?
Ich denke, "gar nicht" ist hier eine sinnvolle Antwort ;)
Geht das wirklich nicht anders? Das war nur meine eigentliche Frage! Ich habe die Dateinamen der Files und will sie hochladen ohne sie über Post-Request zu schicken...
Die Dateinamen sind auf dem Server nichts wert, und clientseitig kriegst du Inhalte der Dateien nicht heraus.

Ich bin geneigt, mitsuhiko zuzustimmen, wenn er dich auf die RFCs verweist, denn dein Posting offenbar nicht gerade großes Wissen um Webprogrammierung ...

@audax
Wir sind hier nicht im Usenet ... "WTF" reicht nicht aus, und schon gar nicht, wenn es so unfreundlich rüberkommt ;)
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Auch wenn es hier heiss her geht, habe ich aufgrund der oben genannten
"String Concatenation" Thematik ein bisschen im Internet gefandet.
Unter Efficient String Concatenation in Python gibt es einen guten Beitrag.

Tabellar
leunam1985
User
Beiträge: 4
Registriert: Montag 26. Mai 2008, 15:39

Danke erstmal für eure Hilfe, habe das Problem nun dank einer 2-Tage Javascript Implementierung in den Griff bekommen und scheine auch mit Python + Turbogears langsam warm zu werden. Danke für all eure Ideen, das sieht doch jetzt schon ganz schön aus.

@Audaux: Ich verbiete dir hiermit ausdrücklich meinen hier veröffentlichen Code in irgendeinerweise wiederzuverwenden, da es sich hierbei um sicherlich nicht dein Eigentum handelt! Wenn ich also meinen Code irgendwo z.B. auf Seiten wie "thedailywtf.com" finde, bekommen wir zwei mächtig Ärger miteinander.

Das Thema hat sich damit erledigt.
Lg, Manu
Benutzeravatar
Blattlaus
User
Beiträge: 55
Registriert: Donnerstag 24. August 2006, 08:55

Achtung, unqualifizierter Kommentar: *mimimi*

Hier audax, ich hab Code für dich den du veröffentlichen kannst:

Code: Alles auswählen

def process_upload(self, **keywds):
        frm_batch_id = keywds['frm_batch_id']
        frm_product = keywds['frm_product']
        additional_info = keywds['additional_info']
        frm_sequence_id = keywds['frm_sequence_id']
        files_for_upload = keywds['files_for_upload']
        num_files = keywds['num_files']
        frm_try = keywds['frm_try']
Mein geistiges Eigentum, hiermit unter Creative Commons Share Alike Lizenz.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

leunam1985 hat geschrieben:Ich verbiete dir hiermit ausdrücklich meinen hier veröffentlichen Code in irgendeinerweise wiederzuverwenden,
Da du wohl kaum Sorge darum haben kannst, dass sich da jemand einen Geschäftsvorteil durch verschafft, scheint dir der Code ja schon peinlich zu sein, wenn dir soviel daran gelegen ist, seine Verbreitung zu vermeiden ;)
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

leunam1985 hat geschrieben:@Audaux: Ich verbiete dir hiermit ausdrücklich meinen hier veröffentlichen Code in irgendeinerweise wiederzuverwenden, da es sich hierbei um sicherlich nicht dein Eigentum handelt! Wenn ich also meinen Code irgendwo z.B. auf Seiten wie "thedailywtf.com" finde, bekommen wir zwei mächtig Ärger miteinander.
Schreib doch bitte wenigstens meinen Namen richtig.

Und nun komm mir doch mit `mächtig Ärger`, dein kleiner Schnipsel ist leider nicht schützenswert (nicht bös gemeint, aber so heißt der Fachausdruck der Juristen). Ich kenn mich da ein wenig aus, schließlich arbeite ich ständig für und mit einem Haufen Juristen :D

Ich verbiete dir hiermit ausdrücklich, meinen hier veröffentlicheten Post zu Quoten oder in sonst irgendeiner Weise zu verwerten oder zu lesen! :roll:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

audax hat geschrieben:Ich verbiete dir hiermit ausdrücklich, meinen hier veröffentlicheten Post zu Quoten oder in sonst irgendeiner Weise zu verwerten oder zu lesen! :roll:
Zur "Sicherheit" solltest du noch den Rechtsweg ausschließen :lol:
lunar

leunam1985 hat geschrieben:Danke erstmal für eure Hilfe
Geschenkt, denn hätte ich gewusst, was von dir noch so kommt, gäbe es zumindest von meiner Seite nichts, wofür du dich bedanken könntest.
leunam1985 hat geschrieben:@Audaux: Ich verbiete dir hiermit ausdrücklich meinen hier veröffentlichen Code in irgendeinerweise wiederzuverwenden, da es sich hierbei um sicherlich nicht dein Eigentum handelt! Wenn ich also meinen Code irgendwo z.B. auf Seiten wie "thedailywtf.com" finde, bekommen wir zwei mächtig Ärger miteinander.
Sowas ist einfach nur arm :roll:
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

http://forums.thedailywtf.com/forums/thread/166686.aspx

Ne Adresse für den Brief des Anwalts gibt auf Anfrage per PN :]
lunar

Ganz unabhängig davon, dass ich dir grundsätzlich völlig zustimme, dass das Verhalten des OP lächerlich und sein Code schlimm ist, frage ich mich doch, ob es jetzt unbedingt nötig gewesen wäre, die Eskalationsspirale nochmal ein Stück weiter zu drehen...
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Es muss doch nicht immer mit jedem, der mir ans Bein pissen möchte wirklich Friede, Freude, Eierkuchen sein...

;)
Antworten