PHP dateiname bei fileupload

MTV-King

phpBB-Profi
ID: 208117
L
21 April 2006
1.488
109
Hallo,

ich bin gerade dabei mich wieder vermehrt mit PHP zu befassen und das wollte ich mit einen Bild-Upload-Script als Beispiel. Eigentlich wollte ich eine Bilderhostingseite betreiben, aber habe mir das anders überlegt und möchte mich doch lieber nur mit PHP beschäftigen.

Aktuell ist mein Script so aufgebaut, dass die Datei noch nicht hochgeladen wird, sondern lediglich ein paar Variablen ausgeben werden, die ich später in einer Datenbank speichern möchte.

Mein Script sieht so aus:
PHP:
dateityp = GetImageSize($_FILES['datei']['tmp_name']);
// $dateityp[2] = 1 -> gif
// $dateityp[2] = 2 -> jpg
// $dateityp[2] = 3 -> png
// $dateityp[2] = 4 -> swf
// $dateityp[2] = 0 - kein Bild
$filename = $_FILES['datei']['name'];
if($dateityp[2] == 1) $filetype = "gif";
elseif($dateityp[2] == 2) $filetype = "jpg";
elseif($dateityp[2] == 3) $filetype = "png";
$uploadtime = time();
$ip = $_SERVER["REMOTE_ADDR"];

echo "filename: ".$filename."<br>filetype: ".$filetype."<br>uploadtime: ".$uploadtime."ip: ".$ip;

Aktuelles Problem: Ich möchte den Dateinamen so ändern, dass keine Zahlen, Leerzeichen, Sonderzeichen, Umlaute und keine Großbuchstaben mehr darin vorkommen. Der Dateiname soll nur noch aus Kleinbuchstaben und "_" als Ersatz für Leerzeichen bestehen.

So sieht mein Versuch aus:
PHP:
// Dateiname pruefen
$filename = strtolower($filename);
$ersetzen = array('Ä' => 'ae', 'ä' => 'ae', 'Ü' => 'ue', 'ü' => 'ue', 'Ö' => 'oe', 'ö' => 'oe', '0' => '', '1' => '', '2' => '', '3' => '', '4' => '', '5' => '', '6' => '', '7' => '', '8' => '', '9' => '');
$filename = strtr($filename, $ersetzen);
Die Zeilen machen die Großbuchstaben zu Kleinbuchstaben und Zahlen werden gelöscht. Aber die Umlaute werden nicht ersetzt. Woran liegts? Oder gibt es eine einfache Methode (spezielle PHP-Funktionen o.ä.)?
 
Aktuell ist mein Script so aufgebaut, dass die Datei noch nicht hochgeladen wird, [...]
Das glaub ich weniger :ugly: Wäre nix hochgeladen, wäre das $_FILES[]-Array ja leer.

Ok, zum Problem: Auf den ersten Blick sieht das schonmal gut aus.
Umlaute könnte (Vermutung) an UTF-8 liegen. Guck ins Manual zu strtr() und lies dir die Kommentare durch. Dort sind gute Lösungen und Code-Stückchen.
 
Ich weiß zu deinem Problem mit den Umlauten keine Lösung, aber ich hab das ganze mit regulären Ausdrücken gelöst und bisher noch kein Problem gehabt.
Ich poste mal meine Funktion hier rein, weiß nicht ob sie dir hilft, aber jedenfalls hat die bisher auf jeglichem Webspace funktioniert.

PHP:
/*
 * function getValidFilename
 * returns valid filenames, stripping invalid letters
 * 
 * @param $_filename (string): original filename
 * @param $_ending (array || string || bool): allowed endings
 * 					array: array of strings that are allowed endings
 * 					string: allowed ending (one only)
 * 					string='': No . allowed in name
 * 					bool=true: file must have ending
 * 					bool=false: don't care about ending
 * 
 * @return (string): New filename or false if an error occured
 */
public static function getValidFilename($_filename, $_ending=false) {
	//echo $_filename.'<br />';
	if(!is_string($_filename)) {
		trigger_error('Filesystem::getValidFilename - Given parameter filename is not a valid string', E_USER_WARNING);
		return false;
	} elseif(!is_bool($_ending) && !is_array($_ending) && !is_string($_ending)) {
		trigger_error('Filesystem::getValidFilename - Given parameter ending is an invalid filetype', E_USER_WARNING);
		return false;
	} elseif(is_string($_ending) && $_ending != '' && !preg_match('/\([a-z1-9_]+(\|[a-z1-9_]+)*\)/', $_ending)) {	# test if string is no regexp pattern
		trigger_error('Filesystem::getValidFilename - File has invalid ending', E_USER_NOTICE);
		return false;
	}

	$_filename = strtolower($_filename);
	$replace = array(
		'/ä/i' => 'ae',
		'/ü/i' => 'ue',
		'/ö/i' => 'oe',
		'/ß/i' => 'ss',
		'/\040/i' => '_',
		'/[^a-z0-9_\.\-]/i' => ''
	);
	
	if(is_string($_ending) && $_ending == '') {
		$replace['/\./'] = '_';
	}

	$_filename = preg_replace(array_keys($replace), array_values($replace), $_filename);
	# Check if filename is valid
	$regex = '';
	if(is_array($_ending)) {
		if(!@Arrays::doDeleteArrayElement($_ending, ''))
			$regex = '(\.('.implode('|', $_ending).'))$';
		else
			$regex = '([\.('.implode('|', $_ending).')]?)$';
	} elseif(is_string($_ending) && $_ending != '') {
		$regex = '\.'.$_ending;
	} elseif($_ending) {
		$regex = '\.[a-z0-9_\.\-]+';
	}
	if(preg_match('/^[a-z0-9_\.\-]+'.$regex.'/', $_filename))
		return $_filename;
	else {
		trigger_error('Filesystem::getValidFilename - Filename ("'.$_filename.'") has an invalid ending', E_USER_WARNING);
		return false;
	}
}
 
@theHacker: Gut, ich meinte lediglich, dass die datei nicht dauerhaft abgespeichert wird.

@Astrodan: Danke für die Funktion, aber damit komme ich nicht so ganz klar und es werden nicht alle Sonderzeichen entfernt. Daher werde ich mich nach anderen Alternativen umsehen.

Ich habe folgende Funktion mithilfe der Kommentare zu strtr() auf php.net zusammengebastelt:
PHP:
function getRewriteString($string) {
     $string = strtolower(htmlentities($string));
     $string = preg_replace("/&(.)(uml);/", "", $string);
     $string = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "", $string);
     $string = preg_replace("/([^a-z0-9]+)/", "", html_entity_decode($string));
	 $string = preg_replace("/0123456789/", "", $string);
     $string = trim($string, "-");
     return $string;
  }

Und ich muss sagen, dass die Funktion eigentlich genau so arbeitet wie ich es mir Wünsche. Nur werden dort alle Punkte gelöscht, auch die vor der Dateiendung, aber da könnte man vorher mit explode etwas ändern.

Aber ich weiß jetzt nicht, ob die Funktion so wirklich vernünftig ist. Daher würde ich mich über Feedback zur genannten Funktion freuen ;)
 
@Astrodan: Danke für die Funktion, aber damit komme ich nicht so ganz klar und es werden nicht alle Sonderzeichen entfernt.
Hm, lange nicht mehr dran rumgebastelt.. schade eigentlich, muss ich wohl doch noch mal überarbeiten. Hoffentlich merkst keiner, die ist nämlich auch ein paar mal im Einsatz ;).

Ich habe folgende Funktion mithilfe der Kommentare zu strtr() auf php.net zusammengebastelt:
PHP:
function getRewriteString($string) {
     $string = strtolower(htmlentities($string));
     $string = preg_replace("/&(.)(uml);/", "", $string);
     $string = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml);/", "", $string);
     $string = preg_replace("/([^a-z0-9]+)/", "", html_entity_decode($string));
	 $string = preg_replace("/0123456789/", "", $string);
     $string = trim($string, "-");
     return $string;
  }
Kann preg_replace nicht mehrere Argumente als Array übergeben werden? Dann müsstest du es nicht fünf mal aufrufen.

Nur werden dort alle Punkte gelöscht, auch die vor der Dateiendung, aber da könnte man vorher mit explode etwas ändern.
Es sollte auch möglich sein dem RegExp beizubringen, dass ein Punkt drin sein darf. Soweit meine Theorie der RegExp reicht müsstest du dazu nochmal ein . + die erlaubten Zeichen hinter den eigentlichen Namen einbinden. Allerdings hab ich immer tierische Arbeite meine eigenen Ausdrücke zum laufen zu kriegen, also ist auf meine Aussage vermutlich kein Verlass..[/QUOTE]
 
Guten Morgen,

ich habe zu diesem Thema vor längerer Zeit ein Tutorial geschrieben, wie man "Mit PHP suchen und ersetzen" kann. Man findet hier zu auch eine Erklärung, wie man den Dateinamen von Sonderzeichen beziehungsweise Umlaute bereinigt.

Für die Leute die ein Upload Script suchen, können sich mal dieses kostenlose Datei Upload Script ansehen. Das Script unterstützt mehrere Sprachen und ist innerhalb von fünf Minuten auf jeden Webspace installiert.

Grüße Nico