Formularauswertung mit perl im Bezug auf den userseitigen upload von Binärdateie
Reimund
- cgi
Ich bitte um Hilfe, bei dem Problem, eine vom user bereitgestellte Binärdatei, zum Beispiel ein Bild im gif-format via Formular auf meinen Server hochzuladen und vor allem diese Datei dann dort auch wiedraufrufbar speichern zu können.
Momentan bin ich so weit gekommen:
<form enctype="multipart/form-data" action="beispieldatei.pl">
<input name="beispiel" type="file">
<input type="submit" value= und so weiter und so fort...
Mein problem ist, die daten mit PERL so auszuwerten, daß sie beispielsweise in einer gif-datei wiederverwertbar abgespeichert werden können.
PHP3 nützt mir leider GAR NIX.
Ich bedanke mich bereits im voraus für Eure Mithilfe
Grüße, Reimund, Tschüß
Hallo Reimund,
Momentan bin ich so weit gekommen:
<form enctype="multipart/form-data" action="beispieldatei.pl">
<input name="beispiel" type="file">
<input type="submit" value= und so weiter und so fort...
O.K., das ist ja mal nicht so schlecht. _Nur_, Du mußt unbending das Ganze mit der HTTP-Methode 'POST' übertragen. weil mit 'GET' funktionierts sicherlich nicht. (Ich glaub' als ich das das erstemal gemacht habe, bin ich eine Woche dabei gesessen und hab' geflucht wie win Rohrspatz)
Das liegt daran, daß die Daten bei 'POST' anders übertragen werden. Bei 'GET' bekommt das Script die Parameter perl Environment-Variable, bei 'POST' über den STDIN. dadurch wird es erst möglich, größere Datenmengen zu übertragen. Das aber nur so am Rande.
Es müßte also heißen:
<form method="POST" enctype="multipart/form-data" action="beispieldatei.pl">
<input name="beispiel" type="file">
<input type="submit" value= und so weiter und so fort...
Nun zum Perl-Teil:
Ich weiß, es klingt schon etwas stereotyp, aber Du solltest unbedingt das Modul CGI.pm verwenden. Die Diokumentation dazu ist zwar recht umfangreich, weil's so viel kann, aber nicht gerade ein Ausbund an Übersichtlichkeit. Es gibt jedoch einen eigenen Abschnitt, der sich mit dem File-Upload beschäftigt.
Such mal nach "Creating a file upload field".
Das Modul ist, soweit ich weiß, inzwischen Bestandteil der Standardbibliotheken, sollte also kein Problem sein, daß es nicht installiert sein sollte.
Das sieht dann so aus (ich schreib jetzt die Erklärungen gleich als Perl-Kommentare):
#!/usr/bin/perl -w
use CGI;
my($query) = new CGI; # erzeugt ein CGI-Objekt, welches für Ein- und Ausgaben benutz werden kann
my($filename) = $query->param('beispiel');
# in $filename steht jetzt zuerstmal der Filename des Originals, je nach Client-OS und Browser kann das auch was anderes sein.
# Es ist also für die auswertung des Namens etwas Flexibilität notwendig
# Für die Auswertung des Dateityps würde ich den Namen jedoch nicht heranziehen, da es sonst zu Problemem kommen kann.
# Ich denk da nur an den Mac, dessen Benutzer ja nicht den Dateityp via Extensions festlegen, sie also auch nicht zwangsläufig verwenden
my($type) = $query->uploadInfo($filename)->{'Content-Type'};
my($savefilename,$url);
my(
if ($type = /^image/(gifjpeg)$/) # das ist nur so als Beispiel gedacht
{
($savefilename,$url) = &generiereName($filename,$1); # siehe weiter unten
}
else
{
&exitwithError("Ungültiger Dateityp, nur GIF und JPEG sind erlaubt"); # das ist eine Pseudofunktion, gibt's normalerweise nicht wirklich ;-)
}
my($fh) = $query->upload('beispiel'); # ab Version 2.47, sonst im nachfolgenden statt '$fh' '$filename' verwenden, sollte auch gehen.
open(OUT, ">$savefilename) or &exitwithError("Kann Zieldatei nicht schreiben");
binmode(OUT); # ein Tribut an Win32, unter Linux gilt: nutzts nix, dann schadets auch nix ;-)
print OUT while <$filename>; # raus mit dem Inhalt der Datei
print "Danke für das übertragen der Datei $filename, sie ist unter $url erreichbar"; # oder so, natürlich schöner :-)
exit;
So das ist einmal der Grundstock. Jetzt hab' ich mich recht elegant um das generieren des Filenamens gedrückt.
Das ist eigentlich auch der schwierigste Teil des ganzen, weil Du dabei natürlich einiges über die Struktur des Servers wissen mußt.
Du mußt unbedingt wissen, wie das Mapping des Webbereichs zum realen Filesystems ist.
Wenn also beispielsweise der URL '/images' auf dem Ordner '/usr/local/httpd/htdocs/images' gemappt ist, dann mußt du dem auch Rechnung tragen.
Wichtig ist noch wie Du die Dateien benennen willst, mit dem Originalnamen oder laufenden Nummern oder wie auch immer.
ich mach's mir jetzt einfach und gehe davon aus daß es eine Funktion 'getnewname()' gibt, welche das für uns erledigt.
sub generiereName
{
my($filename,$ext) = @_;
my($newname) = &getnewname($filename,$ext);
return("/usr/local/httpd/htdocs/images/$newname","/images/$newname");
}
Sowas in der Art. Wobei es natürlich unschön ist, das Mapping hart kodiert in der Funktion durchzuführen. Vielleicht machst Du das über eine Konfigurationsdatei o.ä., damit Du weniger Probleme hast, wenn Du es daheim, lokal ausprobierst und dan auf dem öffentlichen Webserver auch verwenden willst.
So, ich denke das wars.
Ich hoffe, daß es Dir weiterhilft
Klaus
Danke, Klaus !!!!
Nachdem ich alles ein wenig an meine Gegebenheiten angepasst hatte,
funktionierte Alles mit Hilfe Deines Tpps wunderbar.
Du hast ein gut bei mir :-)
Gruß, Reimund