[javascript] How can I get file extensions with JavaScript?

See code:

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

function getFileExtension(filename) {
    /*TODO*/
}

This question is related to javascript file-extension

The answer is


fetchFileExtention(fileName) {
    return fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 2);
}

var extension = fileName.substring(fileName.lastIndexOf('.')+1);

return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

edit: Strangely (or maybe it's not) the $1 in the second argument of the replace method doesn't seem to work... Sorry.


function func() {
  var val = document.frm.filename.value;
  var arr = val.split(".");
  alert(arr[arr.length - 1]);
  var arr1 = val.split("\\");
  alert(arr1[arr1.length - 2]);
  if (arr[1] == "gif" || arr[1] == "bmp" || arr[1] == "jpeg") {
    alert("this is an image file ");
  } else {
    alert("this is not an image file");
  }
}

If you are dealing with web urls, you can use:

function getExt(filepath){
     return filepath.split("?")[0].split("#")[0].split('.').pop();
}

getExt("../js/logic.v2.min.js") // js
getExt("http://example.net/site/page.php?id=16548") // php
getExt("http://example.net/site/page.html#welcome.to.me") // html
getExt("c:\\logs\\yesterday.log"); // log

Demo: https://jsfiddle.net/squadjot/q5ard4fj/


function file_get_ext(filename)
    {
    return typeof filename != "undefined" ? filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase() : false;
    }

var file = "hello.txt";
var ext = (function(file, lio) { 
  return lio === -1 ? undefined : file.substring(lio+1); 
})(file, file.lastIndexOf("."));

// hello.txt -> txt
// hello.dolly.txt -> txt
// hello -> undefined
// .hello -> hello

var filetypeArray = (file.type).split("/");
var filetype = filetypeArray[1];

This is a better approach imo.


A one line solution that will also account for query params and any characters in url.

string.match(/(.*)\??/i).shift().replace(/\?.*/, '').split('.').pop()

// Example
// some.url.com/with.in/&ot.s/files/file.jpg?spec=1&.ext=jpg
// jpg

The following solution is fast and short enough to use in bulk operations and save extra bytes:

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

Here is another one-line non-regexp universal solution:

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

Both work correctly with names having no extension (e.g. myfile) or starting with . dot (e.g. .htaccess):

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

If you care about the speed you may run the benchmark and check that the provided solutions are the fastest, while the short one is tremendously fast:

Speed comparison

How the short one works:

  1. String.lastIndexOf method returns the last position of the substring (i.e. ".") in the given string (i.e. fname). If the substring is not found method returns -1.
  2. The "unacceptable" positions of dot in the filename are -1 and 0, which respectively refer to names with no extension (e.g. "name") and to names that start with dot (e.g. ".htaccess").
  3. Zero-fill right shift operator (>>>) if used with zero affects negative numbers transforming -1 to 4294967295 and -2 to 4294967294, which is useful for remaining the filename unchanged in the edge cases (sort of a trick here).
  4. String.prototype.slice extracts the part of the filename from the position that was calculated as described. If the position number is more than the length of the string method returns "".

If you want more clear solution which will work in the same way (plus with extra support of full path), check the following extended version. This solution will be slower than previous one-liners but is much easier to understand.

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"

All three variants should work in any web browser on the client side and can be used in the server side NodeJS code as well.


Wallacer's answer is nice, but one more checking is needed.

If file has no extension, it will use filename as extension which is not good.

Try this one:

return ( filename.indexOf('.') > 0 ) ? filename.split('.').pop().toLowerCase() : 'undefined';

In node.js, this can be achieved by the following code:

var file1 ="50.xsl";
var path = require('path');
console.log(path.parse(file1).name);

i just wanted to share this.

fileName.slice(fileName.lastIndexOf('.'))

although this has a downfall that files with no extension will return last string. but if you do so this will fix every thing :

   function getExtention(fileName){
     var i = fileName.lastIndexOf('.');
     if(i === -1 ) return false;
     return fileName.slice(i)
   }

function func() {
  var val = document.frm.filename.value;
  var arr = val.split(".");
  alert(arr[arr.length - 1]);
  var arr1 = val.split("\\");
  alert(arr1[arr1.length - 2]);
  if (arr[1] == "gif" || arr[1] == "bmp" || arr[1] == "jpeg") {
    alert("this is an image file ");
  } else {
    alert("this is not an image file");
  }
}

I prefer to use lodash for most things so here's a solution:

function getExtensionFromFilename(filename) {
    let extension = '';
    if (filename > '') {
        let parts = _.split(filename, '.');
        if (parts.length >= 2) {
        extension = _.last(parts);
    }
    return extension;
}

function getExt(filename)
{
    var ext = filename.split('.').pop();
    if(ext == filename) return "";
    return ext;
}

function func() {
  var val = document.frm.filename.value;
  var arr = val.split(".");
  alert(arr[arr.length - 1]);
  var arr1 = val.split("\\");
  alert(arr1[arr1.length - 2]);
  if (arr[1] == "gif" || arr[1] == "bmp" || arr[1] == "jpeg") {
    alert("this is an image file ");
  } else {
    alert("this is not an image file");
  }
}

var parts = filename.split('.');
return parts[parts.length-1];

This simple solution

function extension(filename) {
  var r = /.+\.(.+)$/.exec(filename);
  return r ? r[1] : null;
}

Tests

_x000D_
_x000D_
/* tests */_x000D_
test('cat.gif', 'gif');_x000D_
test('main.c', 'c');_x000D_
test('file.with.multiple.dots.zip', 'zip');_x000D_
test('.htaccess', null);_x000D_
test('noextension.', null);_x000D_
test('noextension', null);_x000D_
test('', null);_x000D_
_x000D_
// test utility function_x000D_
function test(input, expect) {_x000D_
  var result = extension(input);_x000D_
  if (result === expect)_x000D_
    console.log(result, input);_x000D_
  else_x000D_
    console.error(result, input);_x000D_
}_x000D_
_x000D_
function extension(filename) {_x000D_
  var r = /.+\.(.+)$/.exec(filename);_x000D_
  return r ? r[1] : null;_x000D_
}
_x000D_
_x000D_
_x000D_


Fast and works correctly with paths

(filename.match(/[^\\\/]\.([^.\\\/]+)$/) || [null]).pop()

Some edge cases

/path/.htaccess => null
/dir.with.dot/file => null

Solutions using split are slow and solutions with lastIndexOf don't handle edge cases.


The following solution is fast and short enough to use in bulk operations and save extra bytes:

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

Here is another one-line non-regexp universal solution:

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

Both work correctly with names having no extension (e.g. myfile) or starting with . dot (e.g. .htaccess):

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

If you care about the speed you may run the benchmark and check that the provided solutions are the fastest, while the short one is tremendously fast:

Speed comparison

How the short one works:

  1. String.lastIndexOf method returns the last position of the substring (i.e. ".") in the given string (i.e. fname). If the substring is not found method returns -1.
  2. The "unacceptable" positions of dot in the filename are -1 and 0, which respectively refer to names with no extension (e.g. "name") and to names that start with dot (e.g. ".htaccess").
  3. Zero-fill right shift operator (>>>) if used with zero affects negative numbers transforming -1 to 4294967295 and -2 to 4294967294, which is useful for remaining the filename unchanged in the edge cases (sort of a trick here).
  4. String.prototype.slice extracts the part of the filename from the position that was calculated as described. If the position number is more than the length of the string method returns "".

If you want more clear solution which will work in the same way (plus with extra support of full path), check the following extended version. This solution will be slower than previous one-liners but is much easier to understand.

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"

All three variants should work in any web browser on the client side and can be used in the server side NodeJS code as well.


I just realized that it's not enough to put a comment on p4bl0's answer, though Tom's answer clearly solves the problem:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");

Code

/**
 * Extract file extension from URL.
 * @param {String} url
 * @returns {String} File extension or empty string if no extension is present.
 */
var getFileExtension = function (url) {
    "use strict";
    if (url === null) {
        return "";
    }
    var index = url.lastIndexOf("/");
    if (index !== -1) {
        url = url.substring(index + 1); // Keep path without its segments
    }
    index = url.indexOf("?");
    if (index !== -1) {
        url = url.substring(0, index); // Remove query
    }
    index = url.indexOf("#");
    if (index !== -1) {
        url = url.substring(0, index); // Remove fragment
    }
    index = url.lastIndexOf(".");
    return index !== -1
        ? url.substring(index + 1) // Only keep file extension
        : ""; // No extension found
};

Test

Notice that in the absence of a query, the fragment might still be present.

"https://www.example.com:8080/segment1/segment2/page.html?foo=bar#fragment" --> "html"
"https://www.example.com:8080/segment1/segment2/page.html#fragment"         --> "html"
"https://www.example.com:8080/segment1/segment2/.htaccess?foo=bar#fragment" --> "htaccess"
"https://www.example.com:8080/segment1/segment2/page?foo=bar#fragment"      --> ""
"https://www.example.com:8080/segment1/segment2/?foo=bar#fragment"          --> ""
""                                                                          --> ""
null                                                                        --> ""
"a.b.c.d"                                                                   --> "d"
".a.b"                                                                      --> "b"
".a.b."                                                                     --> ""
"a...b"                                                                     --> "b"
"..."                                                                       --> ""

JSLint

0 Warnings.


There is a standard library function for this in the path module:

import path from 'path';

console.log(path.extname('abc.txt'));

Output:

.txt

So, if you only want the format:

path.extname('abc.txt').slice(1) // 'txt'

If there is no extension, then the function will return an empty string:

path.extname('abc') // ''

If you are using Node, then path is built-in. If you are targetting the browser, then Webpack will bundle a path implementation for you. If you are targetting the browser without Webpack, then you can include path-browserify manually.

There is no reason to do string splitting or regex.


function file_get_ext(filename)
    {
    return typeof filename != "undefined" ? filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase() : false;
    }

Fast and works correctly with paths

(filename.match(/[^\\\/]\.([^.\\\/]+)$/) || [null]).pop()

Some edge cases

/path/.htaccess => null
/dir.with.dot/file => null

Solutions using split are slow and solutions with lastIndexOf don't handle edge cases.


If you are looking for a specific extension and know its length, you can use substr:

var file1 = "50.xsl";

if (file1.substr(-4) == '.xsl') {
  // do something
}

JavaScript reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr


Try this:

function getFileExtension(filename) {
  var fileinput = document.getElementById(filename);
  if (!fileinput)
    return "";
  var filename = fileinput.value;
  if (filename.length == 0)
    return "";
  var dot = filename.lastIndexOf(".");
  if (dot == -1)
    return "";
  var extension = filename.substr(dot, filename.length);
  return extension;
}

I prefer to use lodash for most things so here's a solution:

function getExtensionFromFilename(filename) {
    let extension = '';
    if (filename > '') {
        let parts = _.split(filename, '.');
        if (parts.length >= 2) {
        extension = _.last(parts);
    }
    return extension;
}

var parts = filename.split('.');
return parts[parts.length-1];

i just wanted to share this.

fileName.slice(fileName.lastIndexOf('.'))

although this has a downfall that files with no extension will return last string. but if you do so this will fix every thing :

   function getExtention(fileName){
     var i = fileName.lastIndexOf('.');
     if(i === -1 ) return false;
     return fileName.slice(i)
   }

var extension = fileName.substring(fileName.lastIndexOf('.')+1);

Code

/**
 * Extract file extension from URL.
 * @param {String} url
 * @returns {String} File extension or empty string if no extension is present.
 */
var getFileExtension = function (url) {
    "use strict";
    if (url === null) {
        return "";
    }
    var index = url.lastIndexOf("/");
    if (index !== -1) {
        url = url.substring(index + 1); // Keep path without its segments
    }
    index = url.indexOf("?");
    if (index !== -1) {
        url = url.substring(0, index); // Remove query
    }
    index = url.indexOf("#");
    if (index !== -1) {
        url = url.substring(0, index); // Remove fragment
    }
    index = url.lastIndexOf(".");
    return index !== -1
        ? url.substring(index + 1) // Only keep file extension
        : ""; // No extension found
};

Test

Notice that in the absence of a query, the fragment might still be present.

"https://www.example.com:8080/segment1/segment2/page.html?foo=bar#fragment" --> "html"
"https://www.example.com:8080/segment1/segment2/page.html#fragment"         --> "html"
"https://www.example.com:8080/segment1/segment2/.htaccess?foo=bar#fragment" --> "htaccess"
"https://www.example.com:8080/segment1/segment2/page?foo=bar#fragment"      --> ""
"https://www.example.com:8080/segment1/segment2/?foo=bar#fragment"          --> ""
""                                                                          --> ""
null                                                                        --> ""
"a.b.c.d"                                                                   --> "d"
".a.b"                                                                      --> "b"
".a.b."                                                                     --> ""
"a...b"                                                                     --> "b"
"..."                                                                       --> ""

JSLint

0 Warnings.


var file = "hello.txt";
var ext = (function(file, lio) { 
  return lio === -1 ? undefined : file.substring(lio+1); 
})(file, file.lastIndexOf("."));

// hello.txt -> txt
// hello.dolly.txt -> txt
// hello -> undefined
// .hello -> hello

This simple solution

function extension(filename) {
  var r = /.+\.(.+)$/.exec(filename);
  return r ? r[1] : null;
}

Tests

_x000D_
_x000D_
/* tests */_x000D_
test('cat.gif', 'gif');_x000D_
test('main.c', 'c');_x000D_
test('file.with.multiple.dots.zip', 'zip');_x000D_
test('.htaccess', null);_x000D_
test('noextension.', null);_x000D_
test('noextension', null);_x000D_
test('', null);_x000D_
_x000D_
// test utility function_x000D_
function test(input, expect) {_x000D_
  var result = extension(input);_x000D_
  if (result === expect)_x000D_
    console.log(result, input);_x000D_
  else_x000D_
    console.error(result, input);_x000D_
}_x000D_
_x000D_
function extension(filename) {_x000D_
  var r = /.+\.(.+)$/.exec(filename);_x000D_
  return r ? r[1] : null;_x000D_
}
_x000D_
_x000D_
_x000D_


I'm many moons late to the party but for simplicity I use something like this

_x000D_
_x000D_
var fileName = "I.Am.FileName.docx";_x000D_
var nameLen = fileName.length;_x000D_
var lastDotPos = fileName.lastIndexOf(".");_x000D_
var fileNameSub = false;_x000D_
if(lastDotPos === -1)_x000D_
{_x000D_
    fileNameSub = false;_x000D_
}_x000D_
else_x000D_
{_x000D_
    //Remove +1 if you want the "." left too_x000D_
    fileNameSub = fileName.substr(lastDotPos + 1, nameLen);_x000D_
}_x000D_
document.getElementById("showInMe").innerHTML = fileNameSub;
_x000D_
<div id="showInMe"></div>
_x000D_
_x000D_
_x000D_


var filetypeArray = (file.type).split("/");
var filetype = filetypeArray[1];

This is a better approach imo.


var parts = filename.split('.');
return parts[parts.length-1];

There is a standard library function for this in the path module:

import path from 'path';

console.log(path.extname('abc.txt'));

Output:

.txt

So, if you only want the format:

path.extname('abc.txt').slice(1) // 'txt'

If there is no extension, then the function will return an empty string:

path.extname('abc') // ''

If you are using Node, then path is built-in. If you are targetting the browser, then Webpack will bundle a path implementation for you. If you are targetting the browser without Webpack, then you can include path-browserify manually.

There is no reason to do string splitting or regex.


Don't forget that some files can have no extension, so:

var parts = filename.split('.');
return (parts.length > 1) ? parts.pop() : '';

I just realized that it's not enough to put a comment on p4bl0's answer, though Tom's answer clearly solves the problem:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");

Simple way to get filename even multiple dot in name

var filename = "my.filehere.txt";

file_name =  filename.replace('.'+filename.split('.').pop(),'');

console.log("Filename =>"+file_name);

OutPut : my.filehere

extension = filename.split('.').pop();
console.log("Extension =>"+extension);

OutPut : txt

Try this is one line code


For most applications, a simple script such as

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

would work just fine (as provided by Tom). However this is not fool proof. It does not work if the following file name is provided:

image.jpg?foo=bar

It may be a bit overkill but I would suggest using a url parser such as this one to avoid failure due to unpredictable filenames.

Using that particular function, you could get the file name like this:

var trueFileName = parse_url('image.jpg?foo=bar').file;

This will output "image.jpg" without the url vars. Then you are free to grab the file extension.


_x000D_
_x000D_
// ???????_x000D_
function getFileExtension(file) {_x000D_
  var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i;_x000D_
  var extension = file.match(regexp);_x000D_
  return extension && extension[1];_x000D_
}_x000D_
_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/foo"));_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/foo.BAR"));_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz/foo.bar?key=value#fragment"));_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz.bar?key=value#fragment"));
_x000D_
_x000D_
_x000D_


return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

edit: Strangely (or maybe it's not) the $1 in the second argument of the replace method doesn't seem to work... Sorry.


function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

Tested with

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

Also

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")

_x000D_
_x000D_
// ???????_x000D_
function getFileExtension(file) {_x000D_
  var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i;_x000D_
  var extension = file.match(regexp);_x000D_
  return extension && extension[1];_x000D_
}_x000D_
_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/foo"));_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/foo.BAR"));_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz/foo.bar?key=value#fragment"));_x000D_
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz.bar?key=value#fragment"));
_x000D_
_x000D_
_x000D_


function extension(fname) {
  var pos = fname.lastIndexOf(".");
  var strlen = fname.length;
  if (pos != -1 && strlen != pos + 1) {
    var ext = fname.split(".");
    var len = ext.length;
    var extension = ext[len - 1].toLowerCase();
  } else {
    extension = "No extension found";
  }
  return extension;
}

//usage

extension('file.jpeg')

always returns the extension lower cas so you can check it on field change works for:

file.JpEg

file (no extension)

file. (noextension)


function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

Tested with

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

Also

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")

If you are dealing with web urls, you can use:

function getExt(filepath){
     return filepath.split("?")[0].split("#")[0].split('.').pop();
}

getExt("../js/logic.v2.min.js") // js
getExt("http://example.net/site/page.php?id=16548") // php
getExt("http://example.net/site/page.html#welcome.to.me") // html
getExt("c:\\logs\\yesterday.log"); // log

Demo: https://jsfiddle.net/squadjot/q5ard4fj/


Simple way to get filename even multiple dot in name

var filename = "my.filehere.txt";

file_name =  filename.replace('.'+filename.split('.').pop(),'');

console.log("Filename =>"+file_name);

OutPut : my.filehere

extension = filename.split('.').pop();
console.log("Extension =>"+extension);

OutPut : txt

Try this is one line code


Try this:

function getFileExtension(filename) {
  var fileinput = document.getElementById(filename);
  if (!fileinput)
    return "";
  var filename = fileinput.value;
  if (filename.length == 0)
    return "";
  var dot = filename.lastIndexOf(".");
  if (dot == -1)
    return "";
  var extension = filename.substr(dot, filename.length);
  return extension;
}

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

Keep it simple :)

Edit:

This is another non-regex solution that I believe is more efficient:

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

There are some corner cases that are better handled by VisioN's answer below, particularly files with no extension (.htaccess etc included).

It's very performant, and handles corner cases in an arguably better way by returning "" instead of the full string when there's no dot or no string before the dot. It's a very well crafted solution, albeit tough to read. Stick it in your helpers lib and just use it.

Old Edit:

A safer implementation if you're going to run into files with no extension, or hidden files with no extension (see VisioN's comment to Tom's answer above) would be something along these lines

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

If a.length is one, it's a visible file with no extension ie. file

If a[0] === "" and a.length === 2 it's a hidden file with no extension ie. .htaccess

Hope this helps to clear up issues with the slightly more complex cases. In terms of performance, I believe this solution is a little slower than regex in most browsers. However, for most common purposes this code should be perfectly usable.


Wallacer's answer is nice, but one more checking is needed.

If file has no extension, it will use filename as extension which is not good.

Try this one:

return ( filename.indexOf('.') > 0 ) ? filename.split('.').pop().toLowerCase() : 'undefined';

There's also a simple approach using ES6 destructuring:

_x000D_
_x000D_
const path = 'hello.world.txt'
const [extension, ...nameParts] = path.split('.').reverse();
console.log('extension:', extension);
_x000D_
_x000D_
_x000D_


fetchFileExtention(fileName) {
    return fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 2);
}

A one line solution that will also account for query params and any characters in url.

string.match(/(.*)\??/i).shift().replace(/\?.*/, '').split('.').pop()

// Example
// some.url.com/with.in/&ot.s/files/file.jpg?spec=1&.ext=jpg
// jpg

function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

Tested with

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

Also

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")

"one-liner" to get filename and extension using reduce and array destructuring :

_x000D_
_x000D_
var str = "filename.with_dot.png";_x000D_
var [filename, extension] = str.split('.').reduce((acc, val, i, arr) => (i == arr.length - 1) ? [acc[0].substring(1), val] : [[acc[0], val].join('.')], [])_x000D_
_x000D_
console.log({filename, extension});
_x000D_
_x000D_
_x000D_

with better indentation :

var str = "filename.with_dot.png";
var [filename, extension] = str.split('.')
   .reduce((acc, val, i, arr) => (i == arr.length - 1) 
       ? [acc[0].substring(1), val] 
       : [[acc[0], val].join('.')], [])


console.log({filename, extension});

// {
//   "filename": "filename.with_dot",
//   "extension": "png"
// }

function func() {
  var val = document.frm.filename.value;
  var arr = val.split(".");
  alert(arr[arr.length - 1]);
  var arr1 = val.split("\\");
  alert(arr1[arr1.length - 2]);
  if (arr[1] == "gif" || arr[1] == "bmp" || arr[1] == "jpeg") {
    alert("this is an image file ");
  } else {
    alert("this is not an image file");
  }
}

"one-liner" to get filename and extension using reduce and array destructuring :

_x000D_
_x000D_
var str = "filename.with_dot.png";_x000D_
var [filename, extension] = str.split('.').reduce((acc, val, i, arr) => (i == arr.length - 1) ? [acc[0].substring(1), val] : [[acc[0], val].join('.')], [])_x000D_
_x000D_
console.log({filename, extension});
_x000D_
_x000D_
_x000D_

with better indentation :

var str = "filename.with_dot.png";
var [filename, extension] = str.split('.')
   .reduce((acc, val, i, arr) => (i == arr.length - 1) 
       ? [acc[0].substring(1), val] 
       : [[acc[0], val].join('.')], [])


console.log({filename, extension});

// {
//   "filename": "filename.with_dot",
//   "extension": "png"
// }

function extension(fname) {
  var pos = fname.lastIndexOf(".");
  var strlen = fname.length;
  if (pos != -1 && strlen != pos + 1) {
    var ext = fname.split(".");
    var len = ext.length;
    var extension = ext[len - 1].toLowerCase();
  } else {
    extension = "No extension found";
  }
  return extension;
}

//usage

extension('file.jpeg')

always returns the extension lower cas so you can check it on field change works for:

file.JpEg

file (no extension)

file. (noextension)


I know this is an old question, but I wrote this function with tests for extracting file extension, and her available with NPM, Yarn, Bit.
Maybe it will help someone.
https://bit.dev/joshk/jotils/get-file-extension

function getFileExtension(path: string): string {
    var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i
    var extension = path.match(regexp)
    return extension && extension[1]
}

You can see the tests I wrote here.


function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

Tested with

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

Also

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")

function file_get_ext(filename)
    {
    return typeof filename != "undefined" ? filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase() : false;
    }

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

Keep it simple :)

Edit:

This is another non-regex solution that I believe is more efficient:

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

There are some corner cases that are better handled by VisioN's answer below, particularly files with no extension (.htaccess etc included).

It's very performant, and handles corner cases in an arguably better way by returning "" instead of the full string when there's no dot or no string before the dot. It's a very well crafted solution, albeit tough to read. Stick it in your helpers lib and just use it.

Old Edit:

A safer implementation if you're going to run into files with no extension, or hidden files with no extension (see VisioN's comment to Tom's answer above) would be something along these lines

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

If a.length is one, it's a visible file with no extension ie. file

If a[0] === "" and a.length === 2 it's a hidden file with no extension ie. .htaccess

Hope this helps to clear up issues with the slightly more complex cases. In terms of performance, I believe this solution is a little slower than regex in most browsers. However, for most common purposes this code should be perfectly usable.


Don't forget that some files can have no extension, so:

var parts = filename.split('.');
return (parts.length > 1) ? parts.pop() : '';

For most applications, a simple script such as

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

would work just fine (as provided by Tom). However this is not fool proof. It does not work if the following file name is provided:

image.jpg?foo=bar

It may be a bit overkill but I would suggest using a url parser such as this one to avoid failure due to unpredictable filenames.

Using that particular function, you could get the file name like this:

var trueFileName = parse_url('image.jpg?foo=bar').file;

This will output "image.jpg" without the url vars. Then you are free to grab the file extension.


var parts = filename.split('.');
return parts[parts.length-1];

function getExt(filename)
{
    var ext = filename.split('.').pop();
    if(ext == filename) return "";
    return ext;
}

function extension(fname) {
  var pos = fname.lastIndexOf(".");
  var strlen = fname.length;
  if (pos != -1 && strlen != pos + 1) {
    var ext = fname.split(".");
    var len = ext.length;
    var extension = ext[len - 1].toLowerCase();
  } else {
    extension = "No extension found";
  }
  return extension;
}

//usage

extension('file.jpeg')

always returns the extension lower cas so you can check it on field change works for:

file.JpEg

file (no extension)

file. (noextension)


I'm sure someone can, and will, minify and/or optimize my code in the future. But, as of right now, I am 200% confident that my code works in every unique situation (e.g. with just the file name only, with relative, root-relative, and absolute URL's, with fragment # tags, with query ? strings, and whatever else you may decide to throw at it), flawlessly, and with pin-point precision.

For proof, visit: https://projects.jamesandersonjr.com/web/js_projects/get_file_extension_test.php

Here's the JSFiddle: https://jsfiddle.net/JamesAndersonJr/ffcdd5z3/

Not to be overconfident, or blowing my own trumpet, but I haven't seen any block of code for this task (finding the 'correct' file extension, amidst a battery of different function input arguments) that works as well as this does.

Note: By design, if a file extension doesn't exist for the given input string, it simply returns a blank string "", not an error, nor an error message.

It takes two arguments:

  • String: fileNameOrURL (self-explanatory)

  • Boolean: showUnixDotFiles (Whether or Not to show files that begin with a dot ".")

Note (2): If you like my code, be sure to add it to your js library's, and/or repo's, because I worked hard on perfecting it, and it would be a shame to go to waste. So, without further ado, here it is:

function getFileExtension(fileNameOrURL, showUnixDotFiles)
    {
        /* First, let's declare some preliminary variables we'll need later on. */
        var fileName;
        var fileExt;
        
        /* Now we'll create a hidden anchor ('a') element (Note: No need to append this element to the document). */
        var hiddenLink = document.createElement('a');
        
        /* Just for fun, we'll add a CSS attribute of [ style.display = "none" ]. Remember: You can never be too sure! */
        hiddenLink.style.display = "none";
        
        /* Set the 'href' attribute of the hidden link we just created, to the 'fileNameOrURL' argument received by this function. */
        hiddenLink.setAttribute('href', fileNameOrURL);
        
        /* Now, let's take advantage of the browser's built-in parser, to remove elements from the original 'fileNameOrURL' argument received by this function, without actually modifying our newly created hidden 'anchor' element.*/ 
        fileNameOrURL = fileNameOrURL.replace(hiddenLink.protocol, ""); /* First, let's strip out the protocol, if there is one. */
        fileNameOrURL = fileNameOrURL.replace(hiddenLink.hostname, ""); /* Now, we'll strip out the host-name (i.e. domain-name) if there is one. */
        fileNameOrURL = fileNameOrURL.replace(":" + hiddenLink.port, ""); /* Now finally, we'll strip out the port number, if there is one (Kinda overkill though ;-)). */  
        
        /* Now, we're ready to finish processing the 'fileNameOrURL' variable by removing unnecessary parts, to isolate the file name. */
        
        /* Operations for working with [relative, root-relative, and absolute] URL's ONLY [BEGIN] */ 
        
        /* Break the possible URL at the [ '?' ] and take first part, to shave of the entire query string ( everything after the '?'), if it exist. */
        fileNameOrURL = fileNameOrURL.split('?')[0];

        /* Sometimes URL's don't have query's, but DO have a fragment [ # ](i.e 'reference anchor'), so we should also do the same for the fragment tag [ # ]. */
        fileNameOrURL = fileNameOrURL.split('#')[0];

        /* Now that we have just the URL 'ALONE', Let's remove everything to the last slash in URL, to isolate the file name. */
        fileNameOrURL = fileNameOrURL.substr(1 + fileNameOrURL.lastIndexOf("/"));

        /* Operations for working with [relative, root-relative, and absolute] URL's ONLY [END] */ 

        /* Now, 'fileNameOrURL' should just be 'fileName' */
        fileName = fileNameOrURL;
        
        /* Now, we check if we should show UNIX dot-files, or not. This should be either 'true' or 'false'. */  
        if ( showUnixDotFiles == false )
            {
                /* If not ('false'), we should check if the filename starts with a period (indicating it's a UNIX dot-file). */
                if ( fileName.startsWith(".") )
                    {
                        /* If so, we return a blank string to the function caller. Our job here, is done! */
                        return "";
                    };
            };
        
        /* Now, let's get everything after the period in the filename (i.e. the correct 'file extension'). */
        fileExt = fileName.substr(1 + fileName.lastIndexOf("."));

        /* Now that we've discovered the correct file extension, let's return it to the function caller. */
        return fileExt;
    };

Enjoy! You're Quite Welcome!:


return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

edit: Strangely (or maybe it's not) the $1 in the second argument of the replace method doesn't seem to work... Sorry.


In node.js, this can be achieved by the following code:

var file1 ="50.xsl";
var path = require('path');
console.log(path.parse(file1).name);

If you are looking for a specific extension and know its length, you can use substr:

var file1 = "50.xsl";

if (file1.substr(-4) == '.xsl') {
  // do something
}

JavaScript reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr


I just realized that it's not enough to put a comment on p4bl0's answer, though Tom's answer clearly solves the problem:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");

I'm many moons late to the party but for simplicity I use something like this

_x000D_
_x000D_
var fileName = "I.Am.FileName.docx";_x000D_
var nameLen = fileName.length;_x000D_
var lastDotPos = fileName.lastIndexOf(".");_x000D_
var fileNameSub = false;_x000D_
if(lastDotPos === -1)_x000D_
{_x000D_
    fileNameSub = false;_x000D_
}_x000D_
else_x000D_
{_x000D_
    //Remove +1 if you want the "." left too_x000D_
    fileNameSub = fileName.substr(lastDotPos + 1, nameLen);_x000D_
}_x000D_
document.getElementById("showInMe").innerHTML = fileNameSub;
_x000D_
<div id="showInMe"></div>
_x000D_
_x000D_
_x000D_


I just realized that it's not enough to put a comment on p4bl0's answer, though Tom's answer clearly solves the problem:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");

I know this is an old question, but I wrote this function with tests for extracting file extension, and her available with NPM, Yarn, Bit.
Maybe it will help someone.
https://bit.dev/joshk/jotils/get-file-extension

function getFileExtension(path: string): string {
    var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i
    var extension = path.match(regexp)
    return extension && extension[1]
}

You can see the tests I wrote here.


I'm sure someone can, and will, minify and/or optimize my code in the future. But, as of right now, I am 200% confident that my code works in every unique situation (e.g. with just the file name only, with relative, root-relative, and absolute URL's, with fragment # tags, with query ? strings, and whatever else you may decide to throw at it), flawlessly, and with pin-point precision.

For proof, visit: https://projects.jamesandersonjr.com/web/js_projects/get_file_extension_test.php

Here's the JSFiddle: https://jsfiddle.net/JamesAndersonJr/ffcdd5z3/

Not to be overconfident, or blowing my own trumpet, but I haven't seen any block of code for this task (finding the 'correct' file extension, amidst a battery of different function input arguments) that works as well as this does.

Note: By design, if a file extension doesn't exist for the given input string, it simply returns a blank string "", not an error, nor an error message.

It takes two arguments:

  • String: fileNameOrURL (self-explanatory)

  • Boolean: showUnixDotFiles (Whether or Not to show files that begin with a dot ".")

Note (2): If you like my code, be sure to add it to your js library's, and/or repo's, because I worked hard on perfecting it, and it would be a shame to go to waste. So, without further ado, here it is:

function getFileExtension(fileNameOrURL, showUnixDotFiles)
    {
        /* First, let's declare some preliminary variables we'll need later on. */
        var fileName;
        var fileExt;
        
        /* Now we'll create a hidden anchor ('a') element (Note: No need to append this element to the document). */
        var hiddenLink = document.createElement('a');
        
        /* Just for fun, we'll add a CSS attribute of [ style.display = "none" ]. Remember: You can never be too sure! */
        hiddenLink.style.display = "none";
        
        /* Set the 'href' attribute of the hidden link we just created, to the 'fileNameOrURL' argument received by this function. */
        hiddenLink.setAttribute('href', fileNameOrURL);
        
        /* Now, let's take advantage of the browser's built-in parser, to remove elements from the original 'fileNameOrURL' argument received by this function, without actually modifying our newly created hidden 'anchor' element.*/ 
        fileNameOrURL = fileNameOrURL.replace(hiddenLink.protocol, ""); /* First, let's strip out the protocol, if there is one. */
        fileNameOrURL = fileNameOrURL.replace(hiddenLink.hostname, ""); /* Now, we'll strip out the host-name (i.e. domain-name) if there is one. */
        fileNameOrURL = fileNameOrURL.replace(":" + hiddenLink.port, ""); /* Now finally, we'll strip out the port number, if there is one (Kinda overkill though ;-)). */  
        
        /* Now, we're ready to finish processing the 'fileNameOrURL' variable by removing unnecessary parts, to isolate the file name. */
        
        /* Operations for working with [relative, root-relative, and absolute] URL's ONLY [BEGIN] */ 
        
        /* Break the possible URL at the [ '?' ] and take first part, to shave of the entire query string ( everything after the '?'), if it exist. */
        fileNameOrURL = fileNameOrURL.split('?')[0];

        /* Sometimes URL's don't have query's, but DO have a fragment [ # ](i.e 'reference anchor'), so we should also do the same for the fragment tag [ # ]. */
        fileNameOrURL = fileNameOrURL.split('#')[0];

        /* Now that we have just the URL 'ALONE', Let's remove everything to the last slash in URL, to isolate the file name. */
        fileNameOrURL = fileNameOrURL.substr(1 + fileNameOrURL.lastIndexOf("/"));

        /* Operations for working with [relative, root-relative, and absolute] URL's ONLY [END] */ 

        /* Now, 'fileNameOrURL' should just be 'fileName' */
        fileName = fileNameOrURL;
        
        /* Now, we check if we should show UNIX dot-files, or not. This should be either 'true' or 'false'. */  
        if ( showUnixDotFiles == false )
            {
                /* If not ('false'), we should check if the filename starts with a period (indicating it's a UNIX dot-file). */
                if ( fileName.startsWith(".") )
                    {
                        /* If so, we return a blank string to the function caller. Our job here, is done! */
                        return "";
                    };
            };
        
        /* Now, let's get everything after the period in the filename (i.e. the correct 'file extension'). */
        fileExt = fileName.substr(1 + fileName.lastIndexOf("."));

        /* Now that we've discovered the correct file extension, let's return it to the function caller. */
        return fileExt;
    };

Enjoy! You're Quite Welcome!:


return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

edit: Strangely (or maybe it's not) the $1 in the second argument of the replace method doesn't seem to work... Sorry.


function extension(fname) {
  var pos = fname.lastIndexOf(".");
  var strlen = fname.length;
  if (pos != -1 && strlen != pos + 1) {
    var ext = fname.split(".");
    var len = ext.length;
    var extension = ext[len - 1].toLowerCase();
  } else {
    extension = "No extension found";
  }
  return extension;
}

//usage

extension('file.jpeg')

always returns the extension lower cas so you can check it on field change works for:

file.JpEg

file (no extension)

file. (noextension)


There's also a simple approach using ES6 destructuring:

_x000D_
_x000D_
const path = 'hello.world.txt'
const [extension, ...nameParts] = path.split('.').reverse();
console.log('extension:', extension);
_x000D_
_x000D_
_x000D_