Seite 1 von 1

erste Gehversuche - Dateiupload Skript schmeisst KeyError

Verfasst: Freitag 20. Februar 2009, 14:59
von kunatz
Hallo,

ich unternehme soeben meine ersten Gehversuche mit Python. Ich habe eine statische HTML Seite, in der eine Mail Adresse und eine Datei angegeben werden. Nach Klick auf "Upload" wird beides per "Post" an mein Skript "upload.py" uebergeben.

Meine Inspiration fuer das Skript habe ich im Wesentlichen von hier uebernommen: http://webpython.codepoint.net/cgi_big_file_upload
Interpretiert wird das ganze mit mod-python 3.3.1, Apache 2.2.8 auf einem Ubuntu 8.04 Rechner.

Das ist der Code:

Code: Alles auswählen

import cgi, os
import cgitb; cgitb.enable()

DIR_LENGTH = 8
PASS_LENGTH = 20
WEB_DIR = '/var/www/'
MAILSERVER = 'mailserver'
LOCAL_MAIL = 'mail@adr.tld'
user = ''
passwd = ''
uri = 'http://webserver/'
filedir = ''
message = ''

def checkMail():
   from re import match

   mail = string.lower(req.form['mail'])
   user = ''
   if match('^[a-z.]+@company\.tld$', mail):
      for i in mail:
         if i == '@':
            break
         user = user + i
   return user

def printHTML(message):
   return """\
   <html><body>
   <p>%s</p>
   <p><a href="./index.html">zurueck</a></p>
   </body></html>
   """ % message

# Generator to buffer file chunks
def fbuffer(f, chunk_size=10000):
   while True:
      chunk = f.read(chunk_size)
      if not chunk: break
      yield chunk

def doUpload():
   global fileitem

   # Test if the file was uploaded
   if fileitem.filename:

      # build absolute path to files directory
      dir_path = createDir()
      f = open(os.path.join(dir_path, filename), 'wb', 10000)

      # Read the file in chunks
      for chunk in fbuffer(fileitem.file):
         f.write(chunk)
      f.close()
      return 'Die Datei "%s" wurde erfolgreich hochgeladen!' % filename


def deliverMail():
   import smtplib

   #todo: Link gueltig bis ...
   msg_head = 'From: ' + LOCAL_MAIL + '\r\nTo: ' + email + '\r\nSubject: Dateiupload ' + filename + '\r\n'
   msg = msg_head + 'Login:\t' + user + '\r\nPasswort:\t' + passwd + '\r\nLink:\t' + uri
   server = smtplib.SMTP(MAILSERVER)
   server.sendmail(LOCAL_MAIL, email, msg)
   server.quit()

def createDir():
   import hashlib

   global passwd
   global uri
   passwdHash = ''
   passwd = genRandStr(PASS_LENGTH)
   ### noch unvollstaendig
   passwdHash = hashlib.md5(passwd)
   ###
   filedir = genRandStr(DIR_LENGTH) + '/'
   dir = WEB_DIR + filedir
   uri = uri + filedir + filename
   os.makedirs(dir, mode=700)
   htaccess = open(os.path.join(dir, '.htaccess'), 'w')
   htaccess.write(user + ':' + passwdHash)
   htaccess.close()

   return dir

def genRandStr(length):
   import string
   from random import choice

   chars = string.letters + string.digits
   string = ''
   for i in range(length):
      string = string + choice(chars)

   return string

def main():
   form = cgi.FieldStorage()
   fileitem = form['file']
   # strip leading path from file name to avoid directory traversal attacks
   filename = os.path.basename(fileitem.filename)
   email = form['mail']

   user = checkMail()
   if not user:
      message = 'Ungueltige E-Mail Adresse angegeben!'
      return printHTML(message)

   message = doUpload()
   if not message:
      message = 'Bitte Datei angeben'
      return printHTML(message)

   deliverMail()

   print printHTML(message)

main()
Und das der Fehler:
Traceback (most recent call last):

File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1537, in HandlerDispatch
default=default_handler, arg=req, silent=hlist.silent)

File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1229, in _process_target
result = _execute_target(config, req, object, arg)

File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1128, in _execute_target
result = object(arg)

File "/usr/lib/python2.5/site-packages/mod_python/publisher.py", line 204, in handler
module = page_cache[req]

File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1059, in __getitem__
return import_module(req.filename)

File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 296, in import_module
log, import_path)

File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 680, in import_module
execfile(file, module.__dict__)

File "/var/www/upload.py", line 122, in <module>
main()

File "/var/www/upload.py", line 103, in main
fileitem = form['file']

File "/usr/lib/python2.5/cgi.py", line 567, in __getitem__
raise KeyError, key

KeyError: 'file'
Ich hoffe ich werde jetzt nicht in der Luft zerrissen, fuer meine grauenvolle "Arbeit". ;-)
Vielleicht findet jemand von euch den Fehler. Auch andere Tipps, fuer weiteres erfolgreiches programmieren in Python von euch Profis waeren mir sehr willkommen.
Nach Korrektur tausender Indentation Errors und vergessener Doppelpunkte, bin ich nun leider mit meinem Latein am Ende, und kann nur noch auf euch hoffen.

Trotzdem allen ein schoenes Wochenende und vielen Dank im Voraus!

Verfasst: Freitag 20. Februar 2009, 17:28
von martin101986
Hallo,

erstmal willkommen im Forum. Wie die Exception sagt ist deinem Fieldstorage der Key 'file' unbekannt. Das heißt er bekommt diesen Key und den zugehörigen Wert nicht übergeben.

Ich schätze mal das du bei deinem Eingabefeld das Attribut name="file" vergessen hast anzugeben.

Lass dir mal mit

Code: Alles auswählen

print form.keys()
deine Keys ausgeben und sieh nach welche keys alle darin vorkommen.

Ansonsten poste mal den HTML-Abschnitt wo das Eingabefeld für die Datei vorkommt.

Grüße
Martin [/quote]

Verfasst: Montag 23. Februar 2009, 09:39
von kunatz
Also erstmal vielen Dank fuer deine Antwort, aber das kann's eigentlich nicht sein. Hier ist der HTML Code:
<html>
<body>
<form enctype="multipart/form-data" action="./upload.py" method="post">
<p>Mail: <input type="text" name="mail"></p>
<p>File: <input type="file" name="file"></p>
<p><input type="submit" value="Upload"></p>
</form>
</body>
</html>
Ich bin ratlos. :?

edit:
Auch ein

Code: Alles auswählen

print form.keys()
liefert mir "['mail', 'file'] zurueck.

Verfasst: Montag 23. Februar 2009, 13:58
von kunatz
OK, ich habe mich nochmal eingehender mit mod-python beschaeftigt und meinen Code einem kleinen Rewrite unterzogen. Ich rufe jetzt die main Funktion direkt auf und benutze keinen

Code: Alles auswählen

form = cgi.FieldStorage()
fileitem = form['file']
mehr, sondern übergebe die Parameter direkt an die main Funktion:

Code: Alles auswählen

def main(reg)
   mail = req.form['mail']
   file = req.form['file']
Das Problem ist also geloest. Vielen Dank!

Verfasst: Montag 23. Februar 2009, 16:16
von Leonidas
Guter Tipp für die Zukunft: kein mod_python nutzen. Siehe FAQ.