¿Cómo puedo obtener extensiones de archivos con JavaScript?

Resuelto Sergio del Amo asked hace 16 años • 36 respuestas

Ver código:

var file1 = "50.xsl";
var file2 = "30.doc";
getFileExtension(file1); //returns xsl
getFileExtension(file2); //returns doc

function getFileExtension(filename) {
    /*TODO*/
}
Sergio del Amo avatar Oct 10 '08 18:10 Sergio del Amo
Aceptado

Edición más reciente: muchas cosas han cambiado desde que se publicó inicialmente esta pregunta; hay mucha información realmente buena en la respuesta revisada de Wallacer , así como en el excelente desglose de VisioN.


Editar: solo porque esta es la respuesta aceptada; La respuesta de Wallacer es mucho mejor:

return filename.split('.').pop();

Mi antigua respuesta:

return /[^.]+$/.exec(filename);

Deberías hacerlo.

Editar: en respuesta al comentario de PhiLho, use algo como:

return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;
Tom avatar Oct 10 '2008 11:10 Tom
return filename.split('.').pop();

Editar:

Esta es otra solución sin expresiones regulares que creo que es más eficiente:

return filename.substring(filename.lastIndexOf('.')+1, filename.length) || filename;

Hay algunos casos extremos que se manejan mejor con la respuesta de VisioN a continuación, particularmente archivos sin extensión ( .htaccessetc. incluidos).

Es muy eficaz y maneja los casos de esquina de una manera posiblemente mejor al regresar ""en lugar de la cadena completa cuando no hay ningún punto o ninguna cadena antes del punto. Es una solución muy bien diseñada, aunque difícil de leer. Pégalo en la biblioteca de tus ayudantes y úsalo.

Edición antigua:

Una implementación más segura si va a encontrar archivos sin extensión o archivos ocultos sin extensión (consulte el comentario de VisioN a la respuesta de Tom arriba) sería algo parecido a esto

var a = filename.split(".");
if( a.length === 1 || ( a[0] === "" && a.length === 2 ) ) {
    return "";
}
return a.pop();    // feel free to tack .toLowerCase() here if you want

Si a.lengthes uno, es un archivo visible sin extensión, es decir. archivo

Si a[0] === ""y a.length === 2es un archivo oculto sin extensión, es decir. .htaccess

Esto debería aclarar los problemas con los casos un poco más complejos. En términos de rendimiento, creo que esta solución es un poco más lenta que las expresiones regulares en la mayoría de los navegadores. Sin embargo, para los propósitos más comunes, este código debería ser perfectamente utilizable.

wallacer avatar Jul 29 '2009 22:07 wallacer

La siguiente solución es lo suficientemente rápida y breve para usarla en operaciones masivas y ahorrar bytes adicionales:

 return fname.slice((fname.lastIndexOf(".") - 1 >>> 0) + 2);

Aquí hay otra solución universal de una línea sin expresión regular:

 return fname.slice((Math.max(0, fname.lastIndexOf(".")) || Infinity) + 1);

Ambos funcionan correctamente con nombres que no tienen extensión (por ejemplo, miarchivo ) o que comienzan con .un punto (por ejemplo, .htaccess ):

 ""                            -->   ""
 "name"                        -->   ""
 "name.txt"                    -->   "txt"
 ".htpasswd"                   -->   ""
 "name.with.many.dots.myext"   -->   "myext"

Si le importa la velocidad, puede ejecutar el punto de referencia y comprobar que las soluciones proporcionadas son las más rápidas, mientras que la corta es tremendamente rápida:

Comparación de velocidad

Cómo funciona el corto:

  1. String.lastIndexOfEl método devuelve la última posición de la subcadena (es decir, ".") en la cadena dada (es decir, fname). Si no se encuentra la subcadena, el método devuelve -1.
  2. Las posiciones "inaceptables" del punto en el nombre del archivo son -1y 0, que se refieren respectivamente a nombres sin extensión (p. ej. "name") y a nombres que comienzan con un punto (p. ej. ".htaccess").
  3. El operador de desplazamiento a la derecha de relleno cero ( >>>) si se usa con cero afecta los números negativos que se transforman -1hacia 4294967295y -2hacia 4294967294, lo cual es útil para mantener el nombre del archivo sin cambios en los casos extremos (una especie de truco aquí).
  4. String.prototype.sliceextrae la parte del nombre del archivo de la posición que se calculó como se describe. Si el número de posición es mayor que la longitud de la cadena, el método devuelve "".

Si desea una solución más clara que funcione de la misma manera (además de soporte adicional para la ruta completa), consulte la siguiente versión extendida. Esta solución será más lenta que las anteriores, pero es mucho más fácil de entender.

function getExtension(path) {
    var basename = path.split(/[\\/]/).pop(),  // extract file name from full path ...
                                               // (supports `\\` and `/` separators)
        pos = basename.lastIndexOf(".");       // get last position of `.`

    if (basename === "" || pos < 1)            // if file name is empty or ...
        return "";                             //  `.` not found (-1) or comes first (0)

    return basename.slice(pos + 1);            // extract extension ignoring `.`
}

console.log( getExtension("/path/to/file.ext") );
// >> "ext"

Las tres variantes deberían funcionar en cualquier navegador web del lado del cliente y también pueden usarse en el código NodeJS del lado del servidor.

VisioN avatar Oct 15 '2012 17:10 VisioN
function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

Probado con

"a.b"     (=> "b") 
"a"       (=> "") 
".hidden" (=> "") 
""        (=> "") 
null      (=> "")  

También

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")
PhiLho avatar Oct 10 '2008 11:10 PhiLho