@BlackJak
... Beschränkung des Servers hatte ich auch angenommen - konnte aber beim Googlen nix explizites für Perl finden - Python und Perl arbeiten ja auf der selben Schnittstelle (CGI) und da sollte dies i.e. gleich sein oder??
Array aus Form
also hier der Beta Dirty Hacking Code
Die stats_sid.txt wird per AJAX als Progressbar angezeigt...
Weitere Dateibehandlung usw über andere Scripte....
Code: Alles auswählen
#!/usr/bin/python
import os, sys, time, glob, string
import md5
import cgi
import cgitb
cgitb.enable()
upload_path = os.environ['DOCUMENT_ROOT'] + 'uploads/'
cgi_tmp_file_name = 'cgi_data_tmp_'
message = ''
def readStdin(fnpath, fn, sid):
content_len = int(os.environ['CONTENT_LENGTH']) * 1.
t_start = time.time()
fstat = open(fnpath + "stats_" + sid + '.txt', 'w')
f = open(fnpath + fn + sid, 'w+')
b_read = 0
while True:
data = sys.stdin.read(1024*64) # read 64k at a time
if not data: break
f.write(data)
f.flush() # so the ajax poller gets an accurate reading
b_read += 1024*64
t_elapsed = time.time() - t_start
if t_elapsed >= 1:
b_estimate = b_read / t_elapsed; # in kb/sec
else:
b_estimate = b_read / .5;
b_percent = b_read / content_len * 100. # content_len in kb
if b_percent >= 99:
b_percent = 99
t_est = (content_len - b_read) / b_estimate # in sec
if t_est <= 0.:
t_est = 0.
b_est_percent = b_estimate / content_len * 100. # in percent kb
# % , % per second, kb estimate, est time remaining
fstat.seek(0,0)
fstat.write("%f\n%f\n%f\n%f\n%d\n\n" % (b_percent,b_est_percent,b_estimate,t_est,content_len))
fstat.flush()
time.sleep(0.35)
fstat.seek(0,0)
fstat.write("100.\n%f\n%f\n0.\n%d\n\n" % (b_est_percent,b_estimate,content_len))
fstat.flush()
fstat.close()
f.seek(0)
return f
def writeFileData(fnpath, fi):
# strip leading path from file name to avoid directory traversal attacks
fn = os.path.basename(fi.filename)
path_fn = fnpath + fn
fout_fn = open(path_fn, 'w')
while 1:
chunk = fi.file.read(4096)
if not chunk: break
fout_fn.write(chunk)
fout_fn.close()
if os.path.exists ( path_fn ):
oldumask = os.umask(0)
os.chmod( path_fn, 0755 )
os.umask( oldumask )
return
def killFiles(fnpath, fn, sid):
try:
os.remove(fnpath + fn + sid)
except:
pass
return
# #MAIN# #
# HTMLForm_fileupload.cgi?sid=val
try:
session_id = cgi.parse_qs(os.environ['QUERY_STRING'])['sid'][0]
except:
session_id = "nosid_nosid"
# read in data over stdin and write to a file as the file uploads
cgi_in = readStdin(upload_path, cgi_tmp_file_name, session_id)
form = cgi.FieldStorage(cgi_in)
cgi_in.close()
if form:
f = 0
if form.has_key('file[]'): # we have uploads.
for fileitem in form['file[]']:
if fileitem.file and fileitem.filename:
writeFileData(upload_path, fileitem)
f +=1
message += 'Datei %d uploaded %s<br>' % (f, str(fileitem.filename))
if f:
killFiles(upload_path, cgi_tmp_file_name, session_id)
else:
message = 'keine Datei angegeben'
else:
message = 'keine Dateifeld'
else:
message = "keine Formulardaten eingegangen"
print """\
Content-Type: text/html\n
<html><body>"""
print "<p>%s</p></body></html>" % (message,)
Weitere Dateibehandlung usw über andere Scripte....
gruss x-herbert
Hier wird für meinen Geschmack einmal zuviel kopiert. Das `readStdin()` speichert die Daten auf Platte, `cgi.FieldStorage()` kopiert diese Datei nochmal in temporäre Dateien und dann werden die mit `writeFileData()` *nochmal* kopiert.
Es wäre vielleicht effizienter wenn man `sys.stdin` in einem Datei-ähnlichem Objekt kapselt, das einfach die gelesenen Bytes mitzählt und Methoden zur Abfrage der "Statistik" zur Verfügung stellt.
Das AJAX-Pollen von der Datei ist ein bisschen fragil. In den allermeisten Fällen werden die paar Daten wahrscheinlich atomar geschrieben, aber sauber ist das nicht. Und ich bin mir nicht so sicher ob man die Dateien für die Daten nicht besser als Binärdateien öffnet!?
Ansonsten: ``float(string)`` ist etwas einfacher und direkter als ``int(string) * 1.``
Zu `b_read` würde ich die tatsächlich gelesene Anzahl von Bytes addieren und keine Konstante.
Pfadnamen mit `os.path.join()` zusammensetzen.
Für's kopieren von Dateien gibt's im Modul `shutil` fertige Funktionen.
``return`` ohne alles ist am Ende einer Funktion nicht nötig.
Bei ``'%s' % str(obj)`` ist das `str()` überflüssig. Diese Umwandlung macht das '%s' schon.
Es wäre vielleicht effizienter wenn man `sys.stdin` in einem Datei-ähnlichem Objekt kapselt, das einfach die gelesenen Bytes mitzählt und Methoden zur Abfrage der "Statistik" zur Verfügung stellt.
Das AJAX-Pollen von der Datei ist ein bisschen fragil. In den allermeisten Fällen werden die paar Daten wahrscheinlich atomar geschrieben, aber sauber ist das nicht. Und ich bin mir nicht so sicher ob man die Dateien für die Daten nicht besser als Binärdateien öffnet!?
Ansonsten: ``float(string)`` ist etwas einfacher und direkter als ``int(string) * 1.``
Zu `b_read` würde ich die tatsächlich gelesene Anzahl von Bytes addieren und keine Konstante.
Pfadnamen mit `os.path.join()` zusammensetzen.
Für's kopieren von Dateien gibt's im Modul `shutil` fertige Funktionen.
``return`` ohne alles ist am Ende einer Funktion nicht nötig.
Bei ``'%s' % str(obj)`` ist das `str()` überflüssig. Diese Umwandlung macht das '%s' schon.
- veers
- User
- Beiträge: 1219
- Registriert: Mittwoch 28. Februar 2007, 20:01
- Wohnort: Zürich (CH)
- Kontaktdaten:
Ein weg wäre ja make_file im cgi Modul zu überladen. In dem File was du da zurück gibst kannst du dich dann in die write Methode hängen.
Die alternative wäre natürlich einfach per Ajax die Grösse der hochgeladenen Datei zu messen. Vermutlich das einfachste
Die alternative wäre natürlich einfach per Ajax die Grösse der hochgeladenen Datei zu messen. Vermutlich das einfachste
@BlackJack
mit float, b_read, return und %s hast Du natürlich recht!!
Zum Thema Ajax-Polling:
es gibt (wie schon erleutert) zwei generelle Wege:
1.) ich schreibe eine Statistikdatei (wie hier)
2.) ich "beobachte" die Temp-Datei von außen
Generell würde ich auch Punkt 2 vorziehen, aber ich muss die Sachen in ein bestehendes Projekt einfügen und muss sukzessive die Dinge ändern - daher erstmal stats_sid.txt.
Beim Beobachten von Außen muss ich (warscheinlich ??) irgendwo die CONTENT_LENGHT ablegen, um die 100%-Bezugsgröße zu haben.
Frage: Könnte man nicht in dem vorliegenden Fall das StdIn durchschleusen, zählen und direkt an cgi.FieldStorage weitergeben
geht sowas wie
Übrigens, ich konnte nicht erkennen, dass cgi.FieldStorage nochmal eine temporäre Datei anlegt. Die Reihenfolge dürfte genau umgekehrt sein: writeFileData() legt eine temp. Datei an, die dann den Defaultparameter fp (stdin) von FieldStorage überschreibt.
Thema: Öffnen als Binärdateien - ich habe beides gefunden als w bzw. wb und keine eindeutige Aussage, dass man unbedingt wb nehmen muss...
Ich bin keinerlei "Beratungsresitent" und kein großer "Hirsch" in Python dass ich nicht noch ´ne Menge lernen könnte!! Da Python (meiner Meinung nach) gegenüber Ruby den Zug "AJAX" etwas verpasst hat, wäre hier die Gelegenheit ein Stück aufzuholen....
["Überholen ohne Aufzuholen" {Walter Ulbricht 1970} hate zwar schon damals nicht funktioniert, aber man sollte es probieren...]
mit float, b_read, return und %s hast Du natürlich recht!!
Zum Thema Ajax-Polling:
es gibt (wie schon erleutert) zwei generelle Wege:
1.) ich schreibe eine Statistikdatei (wie hier)
2.) ich "beobachte" die Temp-Datei von außen
Generell würde ich auch Punkt 2 vorziehen, aber ich muss die Sachen in ein bestehendes Projekt einfügen und muss sukzessive die Dinge ändern - daher erstmal stats_sid.txt.
Beim Beobachten von Außen muss ich (warscheinlich ??) irgendwo die CONTENT_LENGHT ablegen, um die 100%-Bezugsgröße zu haben.
Frage: Könnte man nicht in dem vorliegenden Fall das StdIn durchschleusen, zählen und direkt an cgi.FieldStorage weitergeben
geht sowas wie
Code: Alles auswählen
def umleitung(dateistromstückchen):
zähle bits
return dateistromstückchen
form = cgi.FieldStorage(umleitungsys.stdin.read(1024))
Thema: Öffnen als Binärdateien - ich habe beides gefunden als w bzw. wb und keine eindeutige Aussage, dass man unbedingt wb nehmen muss...
Ich bin keinerlei "Beratungsresitent" und kein großer "Hirsch" in Python dass ich nicht noch ´ne Menge lernen könnte!! Da Python (meiner Meinung nach) gegenüber Ruby den Zug "AJAX" etwas verpasst hat, wäre hier die Gelegenheit ein Stück aufzuholen....
["Überholen ohne Aufzuholen" {Walter Ulbricht 1970} hate zwar schon damals nicht funktioniert, aber man sollte es probieren...]
gruss x-herbert
Genau das mit der Umleitung hatte ich doch schon vorgeschlagen: Ein Datei-ähnliches Objekt, das mitzählt wieviel gelesen wurde.
Zu den Kopien: Du liesst den Datenstrom von `sys.stdin` ein und schreibst ihn in eine Datei. Diese Datei wird an `FieldStorage` übergeben und geparst, dabei werden die enthaltenen Dateien in temporären Dateien abgelegt. Und diese temporären Dateien werden dann noch einmal von Deinem Code an die endgültige Position kopiert. Und das erste zwischenspeichern müsste man sich sparen können.
Zu den Kopien: Du liesst den Datenstrom von `sys.stdin` ein und schreibst ihn in eine Datei. Diese Datei wird an `FieldStorage` übergeben und geparst, dabei werden die enthaltenen Dateien in temporären Dateien abgelegt. Und diese temporären Dateien werden dann noch einmal von Deinem Code an die endgültige Position kopiert. Und das erste zwischenspeichern müsste man sich sparen können.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Muss man aber, zumindest unter Windows, wo es einen Unterschied zwischen Text und Binärdateien gibt. Wenn du dort Binärdateien ohne das ``b`` Flag schreibst sind sie Schrott, weil die EOL-Zeichen platformspezifisch konvertiert werden.x-herbert hat geschrieben:Thema: Öffnen als Binärdateien - ich habe beides gefunden als w bzw. wb und keine eindeutige Aussage, dass man unbedingt wb nehmen muss...
Ich finde AJAX in sagen wir mal, Django besser als in Rails. Warum? Weil es nicht mitgeliefert ist und ich somit entscheiden kann, ob ich Prototype einsetzen will - will ich meist nicht, bevorzuge jQuery.x-herbert hat geschrieben:Da Python (meiner Meinung nach) gegenüber Ruby den Zug "AJAX" etwas verpasst hat, wäre hier die Gelegenheit ein Stück aufzuholen....
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@BlacJack
@Leonidas:
danke für den Tipp Binary vs. Windows...
Bisher bin ich mit Prototype gut über die Runden gekommen - bei Fehlern lag das an mir und nicht an Prototype..
Ich habe mir jQuery nochmal genauer angesehen - macht auch einen guten Eindruck... besser/schlechter ist hier wohl kaum die Frage, sondern auf welches "Pferd" man setzt und Erfahrungen sammelt - ODER gibt es von Dir noch USPs zu jQuery??
upps.... da reißt der Windschatten langsam ab - da habe ich keine Idee wie man dies realisiertGenau das mit der Umleitung hatte ich doch schon vorgeschlagen: Ein Datei-ähnliches Objekt, das mitzählt wieviel gelesen wurde.
@Leonidas:
danke für den Tipp Binary vs. Windows...
Bisher bin ich mit Prototype gut über die Runden gekommen - bei Fehlern lag das an mir und nicht an Prototype..
Ich habe mir jQuery nochmal genauer angesehen - macht auch einen guten Eindruck... besser/schlechter ist hier wohl kaum die Frage, sondern auf welches "Pferd" man setzt und Erfahrungen sammelt - ODER gibt es von Dir noch USPs zu jQuery??
gruss x-herbert
Ich habe mal so ein Dateiobjekt zusammengebastelt. "Überwachung" und Ausgabe ist mit einem Thread realisiert.
http://paste.pocoo.org/show/2404/
http://paste.pocoo.org/show/2404/
@BJ
habe das ober Posting jetzt erst gesehen...
Oh!
--- ich blick nicht durch ---
~~~~~~~~~~~~~~~~~~~~~~~~
Thema temporäre Dateispeicherung:
ich habe nochmal in das cgi.py gesehen - zwar nicht alles verstanden, aber mir scheint, dass hier aus dem Datenstrom StdIn sofort einzelne Temp-Dateien für die einzenlnen Multipartteile erstellt werden?
habe das ober Posting jetzt erst gesehen...
Oh!
--- ich blick nicht durch ---
~~~~~~~~~~~~~~~~~~~~~~~~
Thema temporäre Dateispeicherung:
ich habe nochmal in das cgi.py gesehen - zwar nicht alles verstanden, aber mir scheint, dass hier aus dem Datenstrom StdIn sofort einzelne Temp-Dateien für die einzenlnen Multipartteile erstellt werden?
Code: Alles auswählen
def read_multi(self, environ, keep_blank_values, strict_parsing):
"""Internal: read a part that is itself multipart."""
ib = self.innerboundary
if not valid_boundary(ib):
raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
self.list = []
klass = self.FieldStorageClass or self.__class__
part = klass(self.fp, {}, ib,
environ, keep_blank_values, strict_parsing)
# Throw first part away
while not part.done:
headers = rfc822.Message(self.fp)
part = klass(self.fp, headers, ib,
environ, keep_blank_values, strict_parsing)
self.list.append(part)
self.skip_lines()
def read_single(self):
"""Internal: read an atomic part."""
if self.length >= 0:
self.read_binary()
self.skip_lines()
else:
self.read_lines()
self.file.seek(0)
bufsize = 8*1024 # I/O buffering size for copy to file
def read_binary(self):
"""Internal: read binary data."""
self.file = self.make_file('b')
todo = self.length
if todo >= 0:
while todo > 0:
data = self.fp.read(min(todo, self.bufsize))
if not data:
self.done = -1
break
self.file.write(data)
todo = todo - len(data)
...
def make_file(self, binary=None):
"""Overridable: return a readable & writable file.
...
"""
import tempfile
return tempfile.TemporaryFile("w+b")
gruss x-herbert
@BJ
hab das Script mal ausprobiert => ich glaube ich verstehe es langsam
kleine Änderung:
hab das Script mal ausprobiert => ich glaube ich verstehe es langsam
kleine Änderung:
Code: Alles auswählen
def main():
reader = None
try:
target = open(os.devnull, 'wb')
filename = 'P:\\record\\Ocean_11.mpg'
reader = MeasuringReader(open(filename, 'rb'),
os.path.getsize(filename))
monitor = TransferMonitor(reader)
monitor.start()
copyfileobj(reader, target)
target.close()
finally:
if reader:
reader.close()
gruss x-herbert
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
blackbird hat seine Erfahrungen mit jQuery zusammengefasst und ich kann dem absolut zustimmen. Mit jQuery zu Arbeiten ist einfach grandios, damit bekommt man innerhalb kürzester Zeit tolle Dinge zusammen und das Chaining ist sehr nützlich.x-herbert hat geschrieben:Ich habe mir jQuery nochmal genauer angesehen - macht auch einen guten Eindruck... besser/schlechter ist hier wohl kaum die Frage, sondern auf welches "Pferd" man setzt und Erfahrungen sammelt - ODER gibt es von Dir noch USPs zu jQuery??
Wenn ich noch eine Library für GUI bräuchte, würde ich Ext mit jQuery kombinieren (da gibt es extra Ext-Integration für).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
... die Sachen sehen schon recht schick aus!
zu meinem Thema:
auf dem Server läuft leider nur eine 2.2.x Version, so dass ich bei Tempfiles das NamedTemporaryFile nicht verwenden kann - meine Idee war einen "Zeiger" auf die temporäre Datei zu setzen um zu sehen wie diese Größer wird.
Als Fazit aus dem Ganzen sehe ich eigentlich nur noch, die Funktion make_file() aus FieldStorage umzubasteln und die durchgeschleusten Byte zu zählen... siehe http://osdir.com/ml/python.cherrypy/200 ... 00107.html
Ansonnsten funktioniert der dirty-hacking-code erstmal und ich muss den nochmal "nachputzen"[/code]
Änderungzu make_file: muss sicher in Funktion read_binary(self) eingebastelt werden
zu meinem Thema:
auf dem Server läuft leider nur eine 2.2.x Version, so dass ich bei Tempfiles das NamedTemporaryFile nicht verwenden kann - meine Idee war einen "Zeiger" auf die temporäre Datei zu setzen um zu sehen wie diese Größer wird.
Als Fazit aus dem Ganzen sehe ich eigentlich nur noch, die Funktion make_file() aus FieldStorage umzubasteln und die durchgeschleusten Byte zu zählen... siehe http://osdir.com/ml/python.cherrypy/200 ... 00107.html
Ansonnsten funktioniert der dirty-hacking-code erstmal und ich muss den nochmal "nachputzen"[/code]
Änderungzu make_file: muss sicher in Funktion read_binary(self) eingebastelt werden
gruss x-herbert
So einfach geht's nicht, weil `make_file()` für die einzelnen übertragenen Dateien aufgerufen wird und nicht für den gesamten Datenstrom. Die Grösse so einer Datei ist also nicht gleich `CONTENT_LENGTH`.
Ich denke, da gibt es einen "logischen Kurzschluss"
Nach bisherigen Kentnisstand kommen doch wohl nur zwei Varianten über die Arbeitsweise von FieldStorage:
1.) FieldStorage speichert erst den StdIn komplett in einer Temp und macht anschließend für die einzelnen Files Temps
2.) FieldStorage fischt sich anhand der Boundaries gleich aus dem StdIn einzelne Temps anhand Files-Boundaries
wenn 1.) dann sollte an der Stelle wo das erste "große" Temp erzeugt und geschrieben wird, die Bytes gezählt werden
wenn 2.) dann wäre es richtig, vorher den Datenstrom abzufangen und zu zählen
[da make_file() also tempfile bei 2.2.x keine Dateinamen zurück gibt, muss an anderer Stelle zum "Einklinken" gesucht werden]
Gruss x-herbert
Nach bisherigen Kentnisstand kommen doch wohl nur zwei Varianten über die Arbeitsweise von FieldStorage:
1.) FieldStorage speichert erst den StdIn komplett in einer Temp und macht anschließend für die einzelnen Files Temps
2.) FieldStorage fischt sich anhand der Boundaries gleich aus dem StdIn einzelne Temps anhand Files-Boundaries
wenn 1.) dann sollte an der Stelle wo das erste "große" Temp erzeugt und geschrieben wird, die Bytes gezählt werden
wenn 2.) dann wäre es richtig, vorher den Datenstrom abzufangen und zu zählen
[da make_file() also tempfile bei 2.2.x keine Dateinamen zurück gibt, muss an anderer Stelle zum "Einklinken" gesucht werden]
Gruss x-herbert
gruss x-herbert
- veers
- User
- Beiträge: 1219
- Registriert: Mittwoch 28. Februar 2007, 20:01
- Wohnort: Zürich (CH)
- Kontaktdaten:
http://paste.pocoo.org/show/2404/ da hat die Klasse TransferMonitor eine Run Methode. Und diese müsstest du anpassen oder mit Callbacks arbeiten.