[WSGI] uploader.py
Verfasst: Montag 21. November 2005, 15:44
EDIT: Die neuste Version pack ich in mein SVN: http://pylucid.python-hosting.com/brows ... _uploader/
Hier ist die erste Version meines Uploaders...
Was ich doof finde... Bei großen Dateien sieht man erstmal nix... Aber ich glaube das läßt sich nicht ändern... Ich hatte zwar diese gepufferte while-Schleife extra dafür eingebaut, die Statusinformationen abgiebt, aber ich glaube das alles kommt erst zum tragen, wenn der Upload schon geschehen ist... Die Preformanze anzeige spiegelt auch IHMO nur die Platten-Schreibgeschwindigkeit mit und nicht die Übertragungszeit 
Wie kann man das besser machen???
Schön wäre ja ein AJAX Upload. Aber JS dürfen keine lokalen Dateien öffnen, was ja auch gut ist
Hier ist die erste Version meines Uploaders...
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" uploader
used WSGI: http://wsgiarea.pocoo.org by Armin Ronacher <armin.ronacher@active-4.com>
Konfiguration:
==============
only_https
Erlaubt nur HTTPs zugriffe, ermittelt mit os.environ["HTTPS"] == "on"
only_auth_users
Erlaubt nur "eingeloggten" Usern den Zugriff. Dabei ist die Apache-Basic-Auth. mit
.htaccess und .htpasswd gemeint s. http://httpd.apache.org/docs/2.0/howto/auth.html
ermittelt mit: os.environ.has_key("AUTH_TYPE") and os.environ.has_key("REMOTE_USER")
send_email_notify = True
Sendet bei jedem gemachten Upload eine eMail mit Informationen.
Ablauf:
=======
Zu jeder hoch geladenen Datei wird eine *.nfo-Textdatei erstellt. Diese ist im
ConfigParser-ini-Format. Es werden Informationen zur Datei gespeichert. u.a.:
* fileinfo: Ergebniss des Linux 'file'-Befehls
* client_info: Username (nur bei only_auth_users=True) und socket.getfqdn()-Info
Beim generieren der Dateiliste werden die *.nfo-Dateien wieder ausgelesen.
"""
__author__ = "Jens Diemer"
__url__ = "http://www.jensdiemer.de"
__license__ = "GNU General Public License (GPL)"
__description__ = "a small upload-form used WSGI"
__version__ = "0.1"
__info__ = 'uploader v%s' % __version__
__history__ = """
v0.1
- erste Version
"""
from __future__ import generators
import sys, os, time, socket, ConfigParser
from wsgi.middlewares import debug; debug.cgi_debug()
from wsgi.wrappers.basecgi import WSGIServer
from wsgi import tools, http
only_https = True
only_auth_users = True
send_email_notify = True
notifer_email_from_adress = "auto_mailer@foobar.de"
notifer_email_to_adress = "uploader@foobar.de"
bufsize = 8192
upload_dir = "uploads"
html_head = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>File Upload</title>
<style type="text/css">
html, body {
padding: 10px;
background-color: #EEF8FF;
}
body {
font-family: tahoma, arial, sans-serif;
color: #000000;
font-size: 0.9em;
background-color: #DBF1FF;
margin: 10px;
padding: 20px;
border: 3px solid #3CBFFF;
}
table.filelist {
border: 1px solid #3CBFFF;
}
.filelist td {
padding-left: 5px;
padding-right: 5px;
}
#footer {
font-size: 0.6em;
}
#footer, #footer a {
margin-top: 1em;
border-top: 1px solid #3CBFFF;
color: #3CBFFF;
text-decoration:none;
text-align: right;
}
</style>
</head>
<body>"""
html_form = """
<h1>File Upload</h1>
<form action="" method="post" enctype="multipart/form-data">
<p><input type="file" name="upload" size="40" />
<input type="submit" value="upload" /></p>
</form>"""
html_footer = """<div id="footer">%s by <a href="http://www.jensdiemer.de">Jens Diemer</a></div>
</body></html>""" % __info__
email_notify_text = """
A person '%(client_info)s' used the uploader.
File information:
%(fileinfo)s
--
This is a automaticly constructed notify message.
created with %(info)s
"""
class Application:
def __init__(self, environ, start_response):
self.environ = environ
self.start_response = start_response
def incoming(self, formdata):
filename = os.path.join(upload_dir, formdata['upload']['filename'])
try:
client_info = socket.getfqdn(os.environ["REMOTE_ADDR"])
except Exception, e:
client_info = "Error: %s" % e
if only_auth_users == True:
# Usernamen hinzufügen
client_info = "%s - %s" % (os.environ["REMOTE_USER"], client_info)
file_obj = formdata['upload']['descriptor']
bytesreaded = 0
try:
f = file(filename, 'wb')
time_threshold = start_time = int(time.time())
while 1:
data = file_obj.read(bufsize)
if not data:
break
bytesreaded += len(data)
f.write(data)
current_time = int(time.time())
if current_time > time_threshold:
yield "<p>read: %sBytes (%s)</p>" % (
bytesreaded, time.strftime("%H:%M:%S", time.localtime())
)
time_threshold = current_time
end_time = time.time()
f.close()
performance = bytesreaded / (end_time-start_time) / 1024
yield "<h2>File saved (%.2fKByes/sec.)</h2>" % performance
except Exception, e:
yield "<h2>ERROR: Can't write file: %s</h2>" % e
return
else:
try:
self.write_info_file(client_info, filename, bytesreaded)
f = file(filename+".nfo", "rU")
fileinfo = f.read()
f.close()
except Exception, e:
yield "<h2>ERROR: Can't write info file: %s</h2>" % e
fileinfo = "ERROR: %s" % e
if send_email_notify == True:
email().send(
from_adress = notifer_email_from_adress,
to_adress = notifer_email_to_adress,
subject = "uploaded: '%s' from '%s'" % (filename, client_info),
text = email_notify_text % {
"client_info" : client_info,
"fileinfo" : fileinfo,
"info" : "%s (Python v%s)" % (__info__, sys.version),
}
)
yield '<a href="?">continue</a>'
def view_uploaded_files(self):
yield "<h2>Filellist:</h2>"
yield '<table class="filelist">\n'
for filename in os.listdir(upload_dir):
if filename.endswith(".nfo"):
continue
yield "<tr>\n"
yield "\t<td>%s</td>\n" % filename
try:
client_info, size, fileinfo, upload_time = self.read_info_file(filename)
except Exception, e:
yield '\t<td colspan="4"><small>Error, get fileinfo: %s</small></td>\n' % e
else:
yield "\t<td>%s</td>\n" % client_info
yield '\t<td align="right">%0.2fKB</td>\n' % (size/1024.0)
yield "\t<td>%s</td>\n" % upload_time
yield "\t<td>%s</td>\n" % fileinfo
yield "</tr>\n"
yield "</table>\n"
def get_file_info(self, filename):
""" Datei Information mit Linux 'file' Befehl zusammentragen """
file_cmd_out = os.popen("file '%s'" % filename).readlines()[0]
file_cmd_out = file_cmd_out.split(":",1)[1]
return file_cmd_out
if file_cmd_out.find("ERROR") != -1:
# Ersatz für >"ERROR" in fileinfo< ;)
return ""
else:
return file_cmd_out
return mtime, size, file_cmd_out
def write_info_file(self, client_info, filename, bytesreaded):
f = file(filename+".nfo", "wU")
config = ConfigParser.ConfigParser()
config.add_section("info")
config.set("info", "client_info", client_info)
config.set("info", "filename", filename)
config.set("info", "bytes", bytesreaded)
config.set("info", "fileinfo", self.get_file_info(filename))
config.set("info", "upload_time", time.strftime("%d %b %Y %H:%M:%S", time.localtime()))
config.write(f)
f.close()
def read_info_file(self, filename):
filename = os.path.join(upload_dir, filename)
f = file(filename+".nfo", "rU")
config = ConfigParser.ConfigParser()
config.readfp(f)
f.close()
client_info = config.get("info", "client_info")
size = int(config.get("info", "bytes"))
fileinfo = config.get("info", "fileinfo")
upload_time = config.get("info", "upload_time")
return client_info, size, fileinfo, upload_time
def __iter__(self):
self.start_response(http.get_status(200), [('Content-Type', 'text/html')])
yield html_head
if only_https == True:
# Nur https Verbindungen "erlauben"
if os.environ.get("HTTPS", False) != "on":
yield "<h2>Error: Only HTTPs connections allow!</h2>"
link = "https://%s%s" % (os.environ["HTTP_HOST"], os.environ["SCRIPT_NAME"])
yield '<h4>try: <a href="%s">%s</a></h4>' % (link, link)
yield html_footer
return
if only_auth_users == True:
# Der User muß über Apache's basic auth eingeloggt sein
if not (os.environ.has_key("AUTH_TYPE") and os.environ.has_key("REMOTE_USER")):
yield "<h2>Error: Only identified users allow!</h2>"
yield html_footer
return
params = tools.get_parameters(self.environ)
if not 'do' in params or params['do'] == 'upload':
formdata = tools.get_files(self.environ)
if formdata:
for line in self.incoming(formdata): yield line
else:
yield html_form
for line in self.view_uploaded_files(): yield line
else:
raise RuntimeError, 'Invalid Request'
yield html_footer
class email:
def send(self, from_adress, to_adress, subject, text):
import time, smtplib
from email.MIMEText import MIMEText
msg = MIMEText(
_text = text,
_subtype = "plain",
_charset = "UTF-8"
)
msg['From'] = from_adress
msg['To'] = to_adress
msg['Subject'] = subject
# Datum nach RFC 2822 Internet email standard.
msg['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
msg['User-Agent'] = "%s (Python v%s)" % (__info__, sys.version)
s = smtplib.SMTP()
s.connect()
s.sendmail(msg['From'], [msg['To']], msg.as_string())
s.close()
#___________________________________________________________________________
if __name__ == '__main__':
app = Application
WSGIServer(app).run()

Wie kann man das besser machen???
Schön wäre ja ein AJAX Upload. Aber JS dürfen keine lokalen Dateien öffnen, was ja auch gut ist
