626

见代码:

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

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

36 回答 36

1028

较新的编辑:自从这个问题最初发布以来,很多事情都发生了变化——在wallacer 的修订答案以及VisioN 的优秀细分中有很多非常好的信息


编辑:仅仅因为这是公认的答案;华莱士的回答确实要好得多:

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

我的旧答案:

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

应该这样做。

编辑:为了回应 PhiLho 的评论,请使用以下内容:

return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;
于 2008-10-10T11:18:02.933 回答
997
return filename.split('.').pop();

编辑:

这是我认为更有效的另一种非正则表达式解决方案:

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

下面VisioN 的回答可以更好地处理一些极端情况,特别是没有扩展名的文件(.htaccess包括等)。

""它非常高效,并且可以通过在点之前没有点或没有字符串时返回而不是完整的字符串来以更好的方式处理极端情况。这是一个精心设计的解决方案,尽管很难阅读。把它放在你的助手库中,然后使用它。

旧编辑:

如果您要遇到没有扩展名的文件或没有扩展名的隐藏文件(请参阅上面的 VisioN 对 Tom 的回答的评论),那么更安全的实现将是这样的

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

如果a.length是一个,它是一个没有扩展名的可见文件,即。文件

如果它是一个没有扩展名的隐藏文件,即a[0] === "".htaccessa.length === 2

这应该可以解决稍微复杂一些的问题。在性能方面,我认为这个解决方案在大多数浏览器中都比正则表达式慢一点。然而,对于最常见的目的,这段代码应该是完全可用的。

于 2009-07-29T22:12:08.347 回答
349

以下解决方案足够且足够,可用于批量操作并节省额外字节:

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

这是另一种单行非正则表达式通用解决方案:

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

两者都可以在没有扩展名的名称(例如myfile)或以.点开头(例如.htaccess)的情况下正常工作:

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

如果您关心速度,您可以运行基准测试并检查提供的解决方案是最快的,而短的解决方案非常快:

速度比较

短的如何工作:

  1. String.lastIndexOf方法返回"."给定字符串 (ie fname) 中子字符串 (ie ) 的最后位置。如果未找到子字符串,则方法返回-1
  2. 文件名中 dot 的“不可接受”位置是-10,它们分别指没有扩展名的名称(例如"name")和以点开头的名称(例如".htaccess")。
  3. 零填充右移运算符( >>>) 如果与零一起使用会影响负数转换-14294967295-24294967294这对于在边缘情况下保持文件名不变(这里有点技巧)很有用。
  4. String.prototype.slice从按照描述计算的位置提取文件名的一部分。如果位置编号大于字符串方法的长度,则返回""

如果您想要以相同方式工作的更清晰的解决方案(加上对完整路径的额外支持),请检查以下扩展版本。此解决方案将比以前的单行方案慢,但更容易理解。

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"

所有三个变体都应该在客户端的任何 Web 浏览器中工作,并且也可以在服务器端 NodeJS 代码中使用。

于 2012-10-15T17:04:31.393 回答
39
function getFileExtension(filename)
{
  var ext = /^.+\.([^.]+)$/.exec(filename);
  return ext == null ? "" : ext[1];
}

经测试

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

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")
于 2008-10-10T11:44:52.197 回答
24
function getExt(filename)
{
    var ext = filename.split('.').pop();
    if(ext == filename) return "";
    return ext;
}
于 2011-10-26T20:45:28.130 回答
24

模块中有一个标准库函数path

import path from 'path';

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

输出:

。文本文件

所以,如果你只想要格式:

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

如果没有扩展名,则该函数将返回一个空字符串:

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

如果您使用的是 Node,那么path是内置的。如果你的目标是浏览器,那么 Webpack 将为path你捆绑一个实现。如果你的目标浏览器没有 Webpack,那么你可以手动包含path- browserify 。

没有理由进行字符串拆分或正则表达式。

于 2018-10-10T10:32:38.590 回答
17
var extension = fileName.substring(fileName.lastIndexOf('.')+1);
于 2011-11-23T17:23:37.713 回答
12

如果您正在处理网页 url,您可以使用:

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

演示:https ://jsfiddle.net/squadjot/q5ard4fj/

于 2017-12-09T23:44:13.807 回答
8
var parts = filename.split('.');
return parts[parts.length-1];
于 2008-10-10T11:18:40.263 回答
8
function file_get_ext(filename)
    {
    return typeof filename != "undefined" ? filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase() : false;
    }
于 2008-10-10T13:53:57.287 回答
8

代码

/**
 * 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
};

测试

请注意,在没有查询的情况下,片段可能仍然存在。

"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 警告。

于 2016-07-09T18:45:49.557 回答
7

快速且与路径一起正常工作

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

一些边缘情况

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

使用 split 的解决方案很慢,而使用 lastIndexOf 的解决方案不处理边缘情况。

于 2013-09-30T04:51:46.137 回答
7

// 获取文件后缀名
function getFileExtension(file) {
  var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i;
  var extension = file.match(regexp);
  return extension && extension[1];
}

console.log(getFileExtension("https://www.example.com:8080/path/name/foo"));
console.log(getFileExtension("https://www.example.com:8080/path/name/foo.BAR"));
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz/foo.bar?key=value#fragment"));
console.log(getFileExtension("https://www.example.com:8080/path/name/.quz.bar?key=value#fragment"));

于 2018-12-03T09:11:09.907 回答
6

我只是想分享这个。

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

尽管这有一个缺点,即没有扩展名的文件将返回最后一个字符串。但如果你这样做,这将解决所有问题:

   function getExtention(fileName){
     var i = fileName.lastIndexOf('.');
     if(i === -1 ) return false;
     return fileName.slice(i)
   }
于 2013-10-04T16:08:09.530 回答
5

我确信将来有人可以并且将会缩小和/或优化我的代码。但是,截至目前,我 200% 确信我的代码适用于每一种独特的情况(例如,仅使用文件名,使用相对根相对绝对URL,使用片段 #标签,使用查询 ?字符串等等否则你可能会决定扔掉它),完美无瑕,并且非常精确。

如需证明,请访问:https ://projects.jamesandersonjr.com/web/js_projects/get_file_extension_test.php

这是 JSFiddle:https ://jsfiddle.net/JamesAndersonJr/ffcdd5z3/

不要过分自信,也不要自吹自擂,但我还没有看到这个任务的任何代码块(在一系列不同的输入参数中找到“正确的”function文件扩展名)可以像这样工作。

注意:根据设计,如果给定的输入字符串不存在文件扩展名,它只会返回一个空白字符串"",而不是错误,也不是错误消息。

它需要两个参数:

  • 字符串: fileNameOrURL (不言自明)

  • 布尔值: showUnixDotFiles(是否显示以点“.”开头的文件)

注意(2):如果您喜欢我的代码,请务必将其添加到您的 js 库和/或 repo 中,因为我努力完善它,浪费了会很可惜。所以,事不宜迟,这里是:

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;
    };

享受!你太客气了!:

于 2017-11-28T03:18:34.520 回答
5

“单线”使用reduce数组解构获取文件名和扩展名:

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});

具有更好的缩进:

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"
// }
于 2018-10-29T14:51:19.167 回答
5

还有一种使用 ES6 解构的简单方法:

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

于 2020-07-08T21:19:06.750 回答
4
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;
}

//用法

扩展名('file.jpeg')

总是返回扩展小写,所以你可以检查它的字段更改工作:

文件.JpEg

文件(无扩展名)

文件。(无扩展名)

于 2008-10-11T16:43:21.033 回答
4

试试这个:

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;
}
于 2011-05-12T04:01:50.817 回答
4

如果您正在寻找特定的扩展名并知道其长度,则可以使用substr

var file1 = "50.xsl";

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

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

于 2014-08-25T10:23:11.897 回答
4

这个简单的解决方案

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

测试

/* tests */
test('cat.gif', 'gif');
test('main.c', 'c');
test('file.with.multiple.dots.zip', 'zip');
test('.htaccess', null);
test('noextension.', null);
test('noextension', null);
test('', null);

// test utility function
function test(input, expect) {
  var result = extension(input);
  if (result === expect)
    console.log(result, input);
  else
    console.error(result, input);
}

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

于 2017-08-28T18:08:44.627 回答
3
return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

编辑:奇怪(或者可能不是)$1替换方法的第二个参数似乎不起作用......对不起。

于 2008-10-10T11:12:04.397 回答
3

我刚刚意识到对 p4bl0 的回答发表评论是不够的,尽管汤姆的回答清楚地解决了这个问题:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");
于 2008-10-10T14:14:10.833 回答
3
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");
  }
}
于 2009-01-16T12:41:00.807 回答
3

对于大多数应用程序,一个简单的脚本,如

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

会工作得很好(由汤姆提供)。然而,这并不是万无一失的。如果提供了以下文件名,它将不起作用:

image.jpg?foo=bar

这可能有点矫枉过正,但我​​建议使用这样的 url 解析器避免由于不可预测的文件名而导致的失败。

使用该特定函数,您可以获得如下文件名:

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

这将输出没有 url 变量的“image.jpg”。然后,您可以自由获取文件扩展名。

于 2011-04-07T16:18:35.173 回答
3

我参加聚会晚了很多个月,但为了简单起见,我使用了这样的东西

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

于 2015-07-04T18:19:50.563 回答
3

一种单行解决方案,它还将考虑查询参数和 url 中的任何字符。

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

// Example
// some.url.com/with.in/&ot.s/files/file.jpg?spec=1&.ext=jpg
// jpg
于 2016-02-20T17:18:29.627 回答
2
fetchFileExtention(fileName) {
    return fileName.slice((fileName.lastIndexOf(".") - 1 >>> 0) + 2);
}
于 2018-03-27T07:21:01.667 回答
1

华莱士的回答很好,但需要再检查一次。

如果文件没有扩展名,它将使用文件名作为扩展名,这是不好的。

试试这个:

return ( filename.indexOf('.') > 0 ) ? filename.split('.').pop().toLowerCase() : 'undefined';
于 2013-03-06T02:24:06.323 回答
1

不要忘记有些文件可以没有扩展名,所以:

var parts = filename.split('.');
return (parts.length > 1) ? parts.pop() : '';
于 2013-05-13T09:32:20.003 回答
1
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
于 2016-04-07T00:24:51.560 回答
1

我知道这是一个老问题,但我用提取文件扩展名的测试编写了这个函数,她可以使用 NPM、Yarn、Bit。
也许它会帮助某人。
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]
}

你可以看到我在这里写的测试。

于 2019-11-20T12:51:11.243 回答
1

获取文件名甚至多个点的简单方法

var filename = "my.filehere.txt";

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

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

输出:my.filehere

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

输出:txt

试试这是一行代码

于 2020-05-07T19:37:13.100 回答
0
var filetypeArray = (file.type).split("/");
var filetype = filetypeArray[1];

这是一个更好的方法。

于 2013-12-06T15:01:00.177 回答
0

在 node.js 中,这可以通过以下代码来实现:

var file1 ="50.xsl";
var path = require('path');
console.log(path.parse(file1).name);
于 2015-07-27T09:40:14.830 回答
0

我更喜欢在大多数事情上使用 lodash,所以这里有一个解决方案:

function getExtensionFromFilename(filename) {
    let extension = '';
    if (filename > '') {
        let parts = _.split(filename, '.');
        if (parts.length >= 2) {
        extension = _.last(parts);
    }
    return extension;
}
于 2018-06-12T22:21:27.217 回答