Función PHP – Extraer ruta, nombre y extensión de un archivo
La curiosidad me la ha despertado el viciño r0sk en su blog a partir de las diferentes opciones que él y sus compañeros de trabajo (saludos a todos de mis partes!) han desarrollado para extraer información de una ruta, nombre y extensión de un archivo dado. Asi que a ellos, a él y a su señora les dedico este post/opinión.
Planteamiento
Algo que en principio parece tan trivial, se complica si empezamos a pensar en las diferentes posibilidades de uso (o mal uso) de una función de este tipo:
- Extensión sin nombre: .htaccess
- Nombre sin extensión: name
- Nombre simplón: name.jpeg
- Nombre complejo: name.surname.gif
- Ruta absoluta: /path/to/name.surname.tar.gz
- Ruta relativa: ../../path/to/name.surname.tar.gz
- BONUS: Cadena vacia para romper la función Comillas vacias ''
- BONUS 2: Cadena malformada para romper la función '/\/.path///file/.gif'
- BONUS 3: Ruta sin archivo '/path/to/folder/'
Requerimientos
Si además queremos aumentar los requerimientos, la cosa se puede complicar bastante:
- Yo como soy un perfeccionista de mierda, quiero 7 Campos:
- ¿ El fichero existe ? Puede ser útil en caso de querer borrar/comprobar
- ¿ El fichero es escribible ? Puede ser útil en caso de querer borrar/editar
- Los permisos del archivo en formato "humano"
- El Nombre sin extensión
- La Extensión sin nombre
- El Archivo (nombre+extensión)
- La Ruta
- La función debe ser totalmente compatible hacia atrás, al menos cubriendo a PHP4
- En la medida de lo posible, no quiero errores si el usuario me pasa datos no válidos
- No quiero cadenas vacias, si uno de los campos no existe quiero un lindo FALSE
- Quiero la ruta sin / al final, añadirla en otras partes del flujo de código es mucho más sencillo que tener que quitarla a posteriori.
Con las manos en la masa
Asi que tras un poco de trapicheo y consulta, he acabado con este engendro, que podría ser mucho más corto, pero cumple todos los requerimientos anteriores:
- function filedata($path) {
- // Vaciamos la caché de lectura de disco
- // Comprobamos si el fichero existe
- // Comprobamos si el fichero es escribible
- // Leemos los permisos del fichero
- // Extraemos la extensión, un sólo paso
- // Primer paso de lectura de ruta
- // Primer paso de lectura de nombre
- // Ajustamos nombre a FALSE si está vacio
- $data["name"] = ($data["name"] ? $data["name"] : FALSE);
- // Ajustamos la ruta a FALSE si está vacia
- $data["path"] = ($data["exists"] ? ($data["name"] ? realpath(array_shift(explode($data["name"],$data["path"]))) : realpath(array_shift(explode($data["ext"],$data["path"])))) : ($data["name"] ? array_shift(explode($data["name"],$data["path"])) : ($data["ext"] ? array_shift(explode($data["ext"],$data["path"])) : rtrim($data["path"],"/")))) ;
- // Ajustamos el nombre a FALSE si está vacio o a su valor en caso contrario
- $data["filename"] = (($data["name"] OR $data["ext"]) ? $data["name"].($data["ext"] ? "." : "").$data["ext"] : FALSE);
- // Devolvemos los resultados
- return $data;
- }
Resultado y demostración
Puedes ver una demostración del uso de esta función en vivo y en directo en la dirección http://www.propiedadprivada.com/lab/phproute/
O bien comprobar el resultado aqui mismo:
Extensión sin nombre: .htaccess
Array (7)
(
| ['exists'] = Boolean(1) TRUE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = String(4) " 0644 "
| ['ext'] = String(8) " htaccess "
| ['path'] = Boolean(0) FALSE
| ['name'] = Boolean(0) FALSE
| ['filename'] = String(9) " .htaccess "
)
Nombre sin extensión: name
Array (7)
(
| ['exists'] = Boolean(1) TRUE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = String(4) " 0644 "
| ['ext'] = Boolean(0) FALSE
| ['path'] = Boolean(0) FALSE
| ['name'] = String(4) " name "
| ['filename'] = String(4) " name "
)
Nombre simplón: name.jpeg
Array (7)
(
| ['exists'] = Boolean(1) TRUE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = String(4) " 0644 "
| ['ext'] = String(4) " jpeg "
| ['path'] = Boolean(0) FALSE
| ['name'] = String(4) " name "
| ['filename'] = String(9) " name.jpeg "
)
Nombre complejo: name.surname.gif
Array (7)
(
| ['exists'] = Boolean(1) TRUE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = String(4) " 0644 "
| ['ext'] = String(3) " gif "
| ['path'] = Boolean(0) FALSE
| ['name'] = String(12) " name.surname "
| ['filename'] = String(16) " name.surname.gif "
)
Ruta absoluta:
/home/httpd/vhosts/propiedadprivada.com/httpdocs/lab/phproute/name.surname.tar.gz
Array (7)
(
| ['exists'] = Boolean(1) TRUE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = String(4) " 0644 "
| ['ext'] = String(2) " gz "
| ['path'] = String(61) " /home/httpd/vhosts/propiedadprivada.com/httpdocs/lab/phproute "
| ['name'] = String(16) " name.surname.tar "
| ['filename'] = String(19) " name.surname.tar.gz "
)
Ruta absoluta que no existe: /path/to/myname.jpeg
Array (7)
(
| ['exists'] = Boolean(0) FALSE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = Boolean(0) FALSE
| ['ext'] = String(4) " jpeg "
| ['path'] = String(9) " /path/to/ "
| ['name'] = String(6) " myname "
| ['filename'] = String(11) " myname.jpeg "
)
Ruta relativa: ../../lab/phproute/name.surname.tar.gz
Array (7)
(
| ['exists'] = Boolean(1) TRUE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = String(4) " 0644 "
| ['ext'] = String(2) " gz "
| ['path'] = String(61) " /home/httpd/vhosts/propiedadprivada.com/httpdocs/lab/phproute "
| ['name'] = String(16) " name.surname.tar "
| ['filename'] = String(19) " name.surname.tar.gz "
)
BONUS: Cadena vacia para romper la función ''
Array (7)
(
| ['exists'] = Boolean(0) FALSE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = Boolean(0) FALSE
| ['ext'] = Boolean(0) FALSE
| ['path'] = String(0) " "
| ['name'] = Boolean(0) FALSE
| ['filename'] = Boolean(0) FALSE
)
BONUS 2: Cadena malformada para romper la función '/\/.path///file/.gif'
Array (7)
(
| ['exists'] = Boolean(0) FALSE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = Boolean(0) FALSE
| ['ext'] = String(3) " gif "
| ['path'] = String(16) " /\/.path///file/ "
| ['name'] = Boolean(0) FALSE
| ['filename'] = String(4) " .gif "
)
BONUS 3: Ruta sin archivo '/path/to/folder/'
Array (7)
(
| ['exists'] = Boolean(0) FALSE
| ['writable'] = Boolean(0) FALSE
| ['chmod'] = Boolean(0) FALSE
| ['ext'] = Boolean(0) FALSE
| ['path'] = String(16) " /path/to/folder "
| ['name'] = Boolean(0) FALSE
| ['filename'] = Boolean(0) FALSE
)
el # Sábado, 16 de octubre del 2010 a las 18:54
Muchísimas gracias, me ha venido genial :-) un trabajo excelente.
el # Jueves, 9 de junio del 2011 a las 22:42
Buen script, funcional y entendible.
¿Existe alguna manera para validar qué tipo de archivo se está posteando… no en base a la cadena de archivo. Ya que podría enviar esto: archivo.exe.gif?
Lo menciono porque se podría enviar un archivo con doble extensión con intensiones perjudiciales.
Saludos
el # Lunes, 21 de noviembre del 2011 a las 17:49
Cuando tu envias un archivo al servidor por el formulario con un input file este mismo maneja un array que dentro del mismo contiene un “type” donde se almacena el tipo de imagen, para hacer una comparativa sencilla seria asi:
if ( ($_FILES["file_img"]["type"]) == ‘image/gif’){
echo “Es una imagen con tipo GIF”;
}else{
echo “No es una imagen con tipo GIF”;
}
Espero te sirva, hay otro metodo que ahorita no recuerdo y ando corto de tiempo para buscarlo, pero es si me escribes a mi correo o entras a mi pagina para que nos comuniquemos y te envie con mas detalle el manejo de imagenes.
el # Miércoles, 1 de febrero del 2012 a las 23:31
hay una funcion en php llamada imagemagick que te puede servir para la matipulación completa de imagenes, espero te sea util
el # Sábado, 4 de febrero del 2012 a las 19:48
Ostia, esto está de puta madre xD
¡Gracias por tu tiempo y por esta función tan genial!
el # Sábado, 4 de febrero del 2012 a las 20:03
Hay un detalle que es raro;
Estoy gestionando la subida de un fichero, y al utilizar la función para recoger los datos de un archivo antes de moverlo, la ruta que me devuelve el Path es la ruta REAL, mientras que lo que hacía falta era la ruta TEMPORAL (ya que luego hay que moverlo).
el # Sábado, 17 de marzo del 2012 a las 04:10
Wuena, super útil.
el # Martes, 22 de mayo del 2012 a las 15:56
me sirvio mucho niño :D gracias
el # Sábado, 10 de noviembre del 2012 a las 07:18
hola.. una pregunta..como imprimes en html los valores que almacenaste en la variable data de filename, ???
el # Domingo, 2 de diciembre del 2012 a las 11:07
Muy buena aportación ;)
Por algo los perfeccionistas son mucho más útiles.
el # Domingo, 2 de diciembre del 2012 a las 11:10
*Ale:
Supongo que es más que obvio que cosas debes modificar.