[PHP] gültigen Dateinamen erzeugen

Astrodan

Gamma Cephei
ID: 119839
L
10 Dezember 2006
1.113
209
Ich habe hier ein Upload-Formular, und würde nun gerne meinem PHP beibringen, die hochgeladene Datei so umzubenennen, dass keine komischen Zeichen á la %20 nötig sind, um darauf zuzugreifen.

Also Beispielsweise sollen sämtliche Sonderzeichen, die eventl. Ungültig sein könnten durch einen _ ersetzet, ein leerzeichen durch _ und ä durch ae etc.
Gibt es dafür eine fertige Funktion, oder muss ich die per Hand schreiben?

Mein Problem ist halt, dass das solange die Dateinamen deutsch bleiben ist die Anzahl an Sonderzeichen überschaubar, aber ich weiß nicht, ob nicht irgendwer auf die Idee kommt sowas wie á da rein zu hauen, oder sonstwas.
Und ich denke mal ein Array mit allen Möglichkeiten aufzustellen dürfte ein wenig komplex werden..
 
PHP:
$dateiname_alt = 'xyz...';

$deteiname_neu = eregi_replace('[[:blank:][:punct:][:space:]]','',$dateiname_alt);

rename($dateiname_alt,$deteiname_neu);

Hier hast du die notwenidgen Daten:

[:alnum:] Alphanumerische Zeichen: [:alpha:] und [:digit:].
[:alpha:] Buchstaben: [:lower:] und [:upper:].
[:blank:] Leerzeichen und Tabulator.
[:cntrl:] Steuerzeichen. Im ASCII sind das die Zeichen 00 bis 1F, und 7F (DEL).
[:digit:] Ziffern: 0, 1, 2,... bis 9.
[:graph:] Graphische Zeichen: [:alnum:] und [:punct:].
[:lower:] Kleinbuchstaben1: nicht notwendigerweise nur von a bis z.
[:print:] Druckbare Zeichen: [:alnum:], [:punct:] und Leerzeichen.
[:punct:] Zeichen wie: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ .
[:space:] Whitespace: Horizontaler und vertikaler Tabulator, Zeilen- und Seitenvorschub, Wagenrücklauf und Leerzeichen.
[:upper:] Großbuchstaben1: nicht notwendigerweise nur von A bis Z.
[:xdigit:] Hexadezimale Ziffern: 0 bis 9, A bis F, a bis f.

P.s. Bitte beachte dass du den (.) Punkt für die Dateiendung brauchst!
 
Argh, ich hasse reguläre Ausdrücke. Das klappt wunderbar, aber sobald ich versuche ihm beizubringen, dass er sämtliche Punkte ignorieren soll gehts schief

Ich glaub ich nehm wirklich nen Array nach dem schema ('ä' => 'ae', ...) und wende den dann mit str_replace an.
Trotzdem danke an alle, die versucht haben zu helfen
 
Öhm.. ich hoffe mich bringt niemand für einen Trippelpost um - aber ich wollte dann doch noch irgendwie das Ergebnis präsentieren, dass einen komplett kleingeschriebenen Dateinamen ausgibt, der garantiert auch im Internet problemlos läuft und mind. ein Zeichen vor und ein Zeichen nach dem Punkt hat.
(ich weiß, davor ist nicht nötig, aber im Normalfall sollte das ja nicht vorkommen)

PHP:
function makeFilenameValid($_filename) {
	$_filename = strtolower($_filename);
	$replace = array(
		'/ä/' => 'ae', 
		'/ü/' => 'ue', 
		'/ö/' => 'oe',
		'/ß/' => 'ss',
		'/\040/' => '_',
		'/[^a-z0-9\.\-]/' => ''
	);
	
	$_filename = preg_replace(array_keys($replace), array_values($replace), $_filename);
	// Check if filename is valid
	if(preg_match('/^[a-z1-9\.\-]+\.[a-z1-9\.\-]+/', $_filename))
		return $_filename;
	else
		return false;
}
 
Im preg_match() solltest du dann aber auch 0-9 machen.

Ne andere Sache: Warum keine Dateien der Form "README" zulassen ?
 
Okey, ich habs mal überarbeitet und ergänzt. Jetzt sind je nach Wunsch des Users die Endungen variabel, und die Möglichkeit der Eingabe ist beliebig.

PHP:
if(function_exists('deleteArrayElement')) {
	// function that deletes $_element from $_array
	function deleteArrayElement(&$_array, $_element) {
		if (false !== ($key = array_search($_element, $_array))) {
			unset($array[$key]);
			return true;
		} else {
			return false;
		}
	}
}

/*
 * function, that makes a valid filename from the string $_filename
 * 
 * @param $_filename (string): Given filename, gfinal filename will be something similiar to this one. Or Equal
 * @param [$_ending=false] (bool || string || array):
 * 			bool:false => Everything is allowed, ending is not necessary
 * 			bool:true => Every ending is allowed, but there has to be an ending
 * 			array => array that conatins the allowed endings as values (use '' for no ending)
 * 			string => string that conatins the allowed endings. Format: (jpeg|jpg|gif|png|42). 
 * 				No ending not supported
 */	
function makeFilenameValid($_filename, $_ending=false) {
	if(!is_string($_filename))
		return false;
	if(!is_bool($_ending) && !is_array($_ending) && !is_string($_ending))
		return false;
	
	$_filename = strtolower($_filename);
	$replace = array(
		'/ä/' => 'ae', 
		'/ü/' => 'ue', 
		'/ö/' => 'oe',
		'/ß/' => 'ss',
		'/\040/' => '_',
		'/[^a-z0-9_\.\-]/' => ''
	);
	
	$_filename = preg_replace(array_keys($replace), array_values($replace), $_filename);
	// Check if filename is valid
	$regex = '';
	if(is_array($_ending)) {
		if(!deleteArrayElement($_ending, ''))
			$regex = '(\.('.implode('|', $_ending).'))$';
		else
			$regex = '([\.('.implode('|', $_ending).')]?)$';
		$regex = '(\.('.implode('|', $_ending).'))$';
	} elseif(is_string($_ending)) {
		$regex = '\.'.$_ending;
	} elseif($_ending) {
		$regex = '\.[a-z0-9_\.\-]+';
	}
	if(preg_match('/^[a-z0-9_\.\-]+'.$regex.'/', $_filename))
		return $_filename;
	else
		return false;
}

Einzig die Sache mit der Übergabe eines Strings als zweites Argument, der falsch formatiert ist könnte Probleme machen. Lohnt es sich, da noch nen preg_match drauf an zu setzen, oder kann ich davon ausgehen, dass der, der umbedingt nen String übergeben will, weiß was er tut?
 
Hallo was willst du denn ignorieren?

[^xy]

dieses ^ Hütchen bedeutet alles Ausser innerhalb Asdrucks oder aussharlb bedeuet es am Anfang (Zeilenanfang)!
Das Ding * Sternchen bedeutet jedes beliebige Zeichen, an dieser Stelle
Der Punkt (.) steht für jedes beliebige Zeichen, außer einem Zeilenumbruch, wenn der m-Modifier nicht explizit angegeben wurde.
Das + Plus steht für Zeichenfolge von mindestens 1 Zeichenlänge
usw...

Eigentlich ist das garnicht schwer, man muss sich nur einmal richtig auseinanderfassen!


[^c] alles Bis auf ein c Achtung aufpassen ob ereg oder ergi oder preg_match etc.. (Groß und Kleinschreibung)

[^abcde] Alles bis auf abcde

[^i]$ Alles bis auf i am Ende!


Sucht einen Text geschrieben Link und wandelt ihn in HTML Code um!

ersetzen:

Code:
'/[^="]{0,1}(http|https|ftp|www)(:\/\/|\.)(www\.|)([^"]+)([[:space:]\]\[])/isU'

/ -> Beginn Ausdruck
[^="] Am Anfang alles ausser = - oder " - Zeichen
{0,1} der Länge 0 oder 1 also nicht wenn der link <a href="https:// etc..
(http|https|ftp|www) http oder https oder ftp oder www Ist das Suchbegriff
:)\/\/|\.) gefolgt von : und // oder .
(www\.|) gefolgt von www. oder nichts
([^"]+) Alles ausser " - Zeichen Mindestlänge 1 oder mehr
([[:space:]\]\[]) Bis zu Leerzeichen, ] - Zeichen oder [ Zeichen

Somit erhälst du den reinen Link!

Denn kannst nun einsetzen
HTML:
' <a href="\1\2\3\4" target="_blank">\1\2\3\4</a>\5',





Was du also brauchst ist sowas:

PHP:
<?php
$dateiname = 'yxshaz$%& .jpg';
	$muster = array(
	'/[^\.[:alpha:][:digit:]]/isU',
	);


	$ersatz = array(
	'',
	);
	echo preg_replace($muster,$ersatz,$dateiname);
?>

Der sagt ersetz mir alles ausser :alpha: :digit: und dem Punkt (.) durch nichts!
 
Zuletzt bearbeitet:
Hmm.. thx für die Antwort, aber ich hab doch schon was ;)

Es ging mir halt darum, dass ich beim hochladen von Dateien diese so umbenennen wollte, dass ich beim aufrufend er Dateien im Browser nicht irgendwelche komischen %-Zeichen da stehen habe, oder, wenn jemand den Dateinamen manuell angibt ungültige Zeichen (wie Slashes etc.) rausgestrichen werden.

Ist halt 50% Optik und 50% Fehlervermeidung.
 
User sind doof :LOL:
entweder du lässt ihn ins Verderben rennen oder baust noch ne Fehlerbehandlung ein

Okey, ich hab mir grad gedacht beschäftigtste dich nochmal mit RegExp, und es kam tatsächlich noch eine weitere Abfrage bei raus. Ergebnis der kompletten Funktion wäre dann:

PHP:
function makeFilenameValid($_filename, $_ending=false) {
	if(!is_string($_filename))
		return false;
	if(!is_bool($_ending) && !is_array($_ending) && !is_string($_ending))
		return false;
	if(is_string($_ending) && !preg_match('/\([a-z0-9_]+(\|[a-z0-9_]+)*\)/', $_ending))
		return false;
	
	$_filename = strtolower($_filename);
	$replace = array(
		'/ä/' => 'ae', 
		'/ü/' => 'ue', 
		'/ö/' => 'oe',
		'/ß/' => 'ss',
		'/\040/' => '_',
		'/[^a-z0-9_\.\-]/' => ''
	);
	
	$_filename = preg_replace(array_keys($replace), array_values($replace), $_filename);
	// Check if filename is valid
	$regex = '';
	if(is_array($_ending)) {
		if(!deleteArrayElement($_ending, ''))
			$regex = '(\.('.implode('|', $_ending).'))$';
		else
			$regex = '([\.('.implode('|', $_ending).')]?)$';
		$regex = '(\.('.implode('|', $_ending).'))$';
	} elseif(is_string($_ending)) {
		$regex = '\.'.$_ending;
	} elseif($_ending) {
		$regex = '\.[a-z0-9_\.\-]+';
	}
	if(preg_match('/^[a-z0-9_\.\-]+'.$regex.'/', $_filename))
		return $_filename;
	else
		return false;
}
 
Ah ja okay! Dann habe ich die Strafe des nicht lese tüchtigen erhalten, und das zu recht! :ugly:

Na dann weiterhin viel Erfolg!