Homepage Inspire-world | Forum
CGI/Perl Workshops Dateiupload inkl. Dateinamenumwandlung und versch. Prüfungen

 Inhaltsverzeichnis/Workshops Übersichtsseite/Dateiupload inkl. Dateinamenumwandlung und versch. Prüfungen
In diesem Workshop geht es um den Dateiupload per Formular.
Da man bei Dateiuploads durchaus auch Schaden anrichten kann (z.B. Dateien überschreiben) habe ich zusätzlich noch eine Dateinamenumwandlung, Prüfung auf eine maximale Dateigröße und eine Prüfung auf erlaubte Dateiendungen integriert.

Zum Schluss wird das ganze noch in einer Textbasierten Datendatei gespeichert und das Resultat an den Browser ausgegeben. Dies dient auch der Erfolgskontrolle des Uploadvorganges.

1. Zuerst das Uploadformular

<HTML>  
<HEAD></HEAD>  
<BODY>  
<FORM ACTION="../cgi-bin/up/up.cgi" METHOD="post" ENCTYPE="multipart/form-data">  

<div align="center"><table bgcolor="#000000" width="450" cellspacing="0" cellpadding="0" border="0">
<tr>
<td>
<table cellspacing="1" cellpadding="2" border="0" width="100%">
<tr>
<td colspan="2" bgcolor="#000080">
<font face="Verdana, Arial" size="2" color="#ffffff"><b>Uploadformular</b></font></td>
</tr>
<tr>
<td bgcolor="#F8F8F8"><font face="Verdana, Arial" size="2">Datei auswählen</font></td>
<td bgcolor="#F8F8F8"><INPUT TYPE="file" NAME="bild"></td>
</tr>
<tr>
<td bgcolor="#F8F8F8"><font face="Verdana, Arial" size="2">Beschreibungstext</font></td>
<td bgcolor="#F8F8F8"><INPUT TYPE="text" NAME="beschreibung"></td>
</tr>
<tr>
<td bgcolor="#F8F8F8" colspan="2" align="center">
<INPUT TYPE="submit" NAME="Submit" VALUE="Absenden"></td>
</tr>
</table>
</td>
</tr>
</table></div>
</FORM> 
</BODY></HTML>
Die zu beachtenden Besonderheiten!

1. ENCTYPE="multipart/form-data muss angegeben sein bei Dateiuploadformularen.
2. <INPUT TYPE="file" NAME="bild"> Input Type=file ist ein Feld zur Dateiauswahl von der Festplatte des Benutzers.

2. Das Uploadscript

Ich habe hier einmal alle Erklärungen zu der Arbeitsweise direkt als Kommentar in das Script geschrieben.
#!/usr/bin/perl
#-------------------------------------------#
# Fehler an den Browser ausgeben
use CGI::Carp qw(fatalsToBrowser);
# CGI Modul nutzen
use CGI;
# Parametervariable festlegen
$a = new CGI;
#-------------------------------------------#

#-------------------------------------------#
# Konfiguration der Pfade, erlaubten Dateitypen und Dateigrößen
#-------------------------------------------#
# Uploadpfad zum Verzeichnis in dem die Dateien gespeichert werden sollen
$upload_verz = "/home/10/hwinspid/upfoto";

# Erlaubte Dateitypen, Durch eine Pipe | trennen
$erlaubte_dateitypen = "gif|jpg";

# Maximale Dateigröße gerundet in KB
$max_dateigroesse = 60;
#-------------------------------------------#
# Parameter und Variablenzuweisung
$dateiname = $a->param("bild");
$beschreibung = $a->param("beschreibung");

# umwandeln von etwaigen Backslashes in /
$dateiname =~ s/.*[\/\\](.*)/$1/;

$upload = $a->param("bild");
#-------------------------------------------#
# Größe der Datei ermitteln
# Durch den Dateitest -s wird die Dateigröße in bytes ermittelt
my $dateigroesse = -s $upload;

# Dateigröße durch 1000 ergibt gerundeten KB Wert
$dateigroesse /= 1000; 

# Ist Dateigröße größer als $max_dateisize ? ...
if ($dateigroesse > $max_dateigroesse)
{
# ... dann Fehlermeldung ausgeben
print "Content-type: text/html\n\n";
print "<p>Datei ist zu groß, höchstens 60kb Die Dateigröße beträgt aber $dateigroesse bytes</p>\n";
# Splitten der Dateigröße am Punkt
# Beispiel 71.539 bytes werden Zerlegt in 71 und 539
($kbsize,$byt) = split(/\./, $dateigroesse);
# Ausgabe des ersten Wertes aus dem Splitting zur Userinformation
print "Dies entspricht etwa $kbsize KB";
# Programmabbruch durch exit
exit;
}
#-------------------------------------------#

# Splitten des Dateinamens in Dateiname und Endung
($bildname,$endung) = split(/\./, $dateiname);

# Abfrage ob Endung erlaubter Dateityp ist
# Der Reguläre Ausdruck "!~ /^\w+\.($erlaubte_dateitypen)/)"
# prüft hier mit $erlaubte_dateitypen ob die Dateiendung
# zulässig ist. 
# /^\w+\. enthält dabei die Zeichen vom Dateianfang, diese wwerden durch
# das vorangestellte ^ Zeichen und w+ geprüft ( \w = Zeichenklasse(0-9a-zA-Z_)
if($dateiname !~ /^\w+\.($erlaubte_dateitypen)/) {

print "Content-type: text/html\n\n";
# Etwaige Fehlermeldung ausgeben
print "Es sind nur Dateien mit der Endung $erlaubte_dateitypen erlaubt";
# Programmabbruch durch exit
exit;
}
#-------------------------------------------#
# Bildname bekommt den Wert von time zugewiesen
# Hiermit wird vermieden das Bilder mit selbem Dateiname überschrieben werden
$bildname = time();
#-------------------------------------------#

# Vorsichtshalber doch noch ein Dateitest mit -e
# - e prüft ob Datei schon vorhanden
if (-e "$upload_verz/$bildname.$endung") {
print "Content-type: text/html\n\n";
print "Datei ist schon vorhanden";
#-------------------------------------------#
} else {
# Alles OK, dann weiter....

# Uploadfile öffnen
open UPLOADFILE, ">$upload_verz/$bildname.$endung";
# Binmode für Upload festlegen
binmode $upload;
# Datei mittels while durchlaufen... 
while ( <$upload> ) {
# ... und schreiben
print UPLOADFILE;
}
# Datei schließen
close UPLOADFILE;
#-------------------------------------------#
# Daten in die Datenbank eintragen
open (FILE, ">>daten.dat");
flock (FILE, 2);
# Daten schreiben, zuerst der umgewandelte Dateiname
# dann der Beschreibungstext, am Ende steht der Orginale Dateiname
print FILE "$bildname.$endung|$beschreibung|$dateiname\n";
close FILE;
#-------------------------------------------# 
print "Content-type: text/html\n\n";
# Ausgabe des Uploadergebnisses
print qq~
<HTML>  
<HEAD>  
<TITLE>Fertig</TITLE>  
</HEAD>
<BODY>
<table bgcolor="#000000" width="500" cellspacing="0" cellpadding="0" border="0">
<tr>
<td>
<table width="100%" cellspacing="1" cellpadding="3" border="0">
<tr>
<td bgcolor="#E7E7E7"><font face="Verdana, Arial" size="2">Bild</font></td>
<td bgcolor="#E7E7E7"><font face="Verdana, Arial" size="2">Beschreibung</font></td>
</tr>
<tr>
<td bgcolor="#E7E7E7"><font face="Verdana, Arial" size="2">
<img src="http://www.inspire4you.de/upfoto/$bildname.$endung" border="0"></font></td>
<td bgcolor="#E7E7E7"><font face="Verdana, Arial" size="2">$beschreibung</font></td>
</tr>
</table>
</td>
</tr>
</table>

</BODY>  
</HTML>
~;

}
# Ende der Veranstaltung ....
Vorteile dieser Methode

1. Die Dateien werden samt Beschreibung in einer solchen Datendatei gespeichert.

1023367835.jpg|Das Bild vom Auto|auto.jpg
1023367877.jpg|Das Bild vom Mororrad|honda.jpg

Dadurch besteht die Möglichkeit auch mit anderen Programmen die Daten auszulesen und darzustellen.

2. Es steht der Dateiname umgewandelt zu "Sekunden.endung" und der Orginalbildname zur Verfügung.
3. Es können zu dem Uploadformular weitere Eingabefelder hinzugefügt werden und die Daten in der Datenbankdatei gespeichert wrden.



 Zum Inhaltsverzeichnis/Workshops Übersichtsseite/Dateiupload inkl. Dateinamenumwandlung und versch. Prüfungen
Autor: Helmut Walter Homepage Inspire-world Fragen, Anregungen und Hinweise bitte in das Forum

Valid HTML 4.0! Valid CSS!