如何使用JavaScript获取文件扩展名?


501

看到代码:

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

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

Answers:


794

较新的编辑:自从最初发布此问题以来,很多事情已经发生了变化-wallacer的修改后答案以及VisioN的出色表现中提供了很多非常好的信息


编辑:仅仅因为这是公认的答案;wallacer的答案确实好得多:

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

我的旧答案:

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

应该做。

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

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

1
两次执行正则表达式是否昂贵?
安德鲁·赫奇斯

5
以下高度评价的答案要好得多。
fletom 2012年

2
不幸的是,两种解决方案都无法使用文件名和.htaccess之类的名称。
VisioN 2012年

3
所有可能的情况都按以下方式处理:return filename.split(“。”)。slice(1).pop()|| “”;
JustAndrei 2014年

1
@JustAndrei仍然不是全部:)对于纯文件名(基本名?),而不是路径,出于实际原因,我认为应该是return filename.substring(0,1) === '.' ? '' : filename.split('.').slice(1).pop() || '';这样的。这也可以处理.file(我认为是Unix隐藏的)文件。那就是如果您想将其保持为单线,这对我来说有点混乱。
kooker 2014年

832
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为1,则为不带扩展名的可见文件。文件

如果a[0] === ""a.length === 2这是一个没有扩展名的隐藏文件。.htaccess

希望这有助于解决稍微复杂一些的问题。在性能方面,我相信该解决方案在大多数浏览器中都比regex慢一些。但是,对于大多数常见目的,此代码应完全可用。


4
我不能对性能发表评论,但是这当然看起来很干净!我在用 +1
pc1oad1etter

6
但是在这种情况下,文件名看起来像filname.tes.test.jpg。请考虑输出。我希望这是错误的。
Fero

19
在这种情况下,输出为“ jpg”
wallacer

1
辉煌!非常感谢。很高兴看到不使用正则表达式的解决方案。我已经用PHP完成了它,它仅使用了几个函数。+1
Bojangles 2010年

3
@wallacer:如果filename实际上没有扩展名怎么办?这不是简单地返回基本文件名吗?
Nicol Bolas

286

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

 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方法返回"."给定字符串(即fname)中子字符串(即)的最后位置。如果未找到子字符串,则方法返回-1
  2. 点在文件名中的“不可接受”位置是-10,分别表示没有扩展名的名称(例如"name")和以点开头的名称(例如".htaccess")。
  3. 零填充右移运算符>>>)如果与零一起使用,将影响负数-14294967295-2转换4294967294,这对于在边缘情况下保持文件名不变(在这里有些技巧)很有用。
  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代码中使用。


5
不起作用。“ /home/user/.app/config”返回“ app / config”,这是完全错误的。
mrbrdo 2013年

33
@mrbrdo不应按问题要求仅使用文件名使用完整路径。投降前请仔细阅读问题。
VisioN

8
为什么要竭尽全力优化如此琐碎的代码行?在JavaScript中很少见到Tilde和bitshift运算符,以至于我无法支持这样的答案。如果需要5个要点来解释1行代码是如何工作的,则最好重写代码,这样它实际上是可以理解的。
杰克逊

6
这一行的速度在任何应用中都不会引起明显变化。很少使用Bitwise,以至于流行的Linter(如JSLint和JSHint)警告不要使用它们。对这种逻辑的性能和紧凑性的痴迷降低了代码的质量。如果代码需要“额外调查”,则我认为它“不好”。
杰克逊

9
@Jackson考虑到这是一个为问题提供多种解决方案的站点,拥有优化性能的解决方案从来不是一件坏事。您说“在任何应用程序中都不会造成明显的变化”完全基于您可以使用的应用程序范围狭窄。此外,它还可以为研究问题的人员提供学习经验,使他们可以优化某些知识。他们正在编写的用于计算密集型应用程序所需的其他代码。
nrylee

33
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")

要使其在IE中工作:var pattern =“ ^。+ \\。([^。] +)$”; var ext = new RegExp(pattern);
spc16670 '16

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

8
返回(ext ===文件名)'':分机;
米歇尔2014年

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


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

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"
"..."                                                                       --> ""

杰林特

0警告。


7

快速并正确使用路径

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

一些边缘情况

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

使用split的解决方案速度很慢,使用lastIndexOf的解决方案无法处理极端情况。


您是什么意思?请在这里参考我的解决方案:stackoverflow.com/a/12900504/1249581。它在所有情况下都能正常工作,并且比任何正则表达式都快得多。
VisioN

我已经列出了一些极端情况。而且您的解决方案无法正确处理它们。就像我已经写过的一样,尝试“ /dir.with.dot/file”。您的代码返回“点/文件”,这简直是错误的。
mrbrdo 2013年

1
没有人要求解析路径。问题是关于从文件名中提取扩展名。
2013年

3
就像我已经告诉您的那样,这从来没有明确说过,处理路径的解决方案显然要有用得多。关于SO问题的答案除了提出问题的人之外,还应该对其他人有用。我真的不认为应该降低处理输入超集的解决方案。
mrbrdo

3
降票是用于将全局变量与一起使用.exec()。您的代码会更好(filename.match(/[^\\/]\.([^\\/.]+)$/) || [null]).pop()
VisioN

6

我只是想分享这个。

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

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

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

据我所记得,slice方法是指数组而不是字符串。对于字符串substr还是substring可以的。
2013年

@VisioN,但我想您应该知道还有String.prototype.slice一个,Array.prototype.slice所以这两种工作方式都有点方法
Hussein Nazzal 2013年

1
是的。你是对的。完全忘记了这种方法。我的错。
2013年

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库和/或回购库中,因为我一直在努力完善它,而浪费将是可耻的。因此,事不宜迟,这里是:

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

请享用!你太客气了!:


1
太棒了 谢谢!
GollyJer

5

// 获取文件后缀名
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"));


5

如果要处理Web 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/


我真的很喜欢您的解决方案。事半功倍。我要用它。
朱尔斯·曼森

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

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

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


1
效果很好,但是您错过了必须删除字符串的所有其他内容的方法:return filename.replace(/^.*?\。([[a-zA-Z0-9] +)$ /, “ $ 1”);
08年

3

我只是意识到仅仅评论p4bl0的答案是不够的,尽管Tom的答案显然解决了这个问题:

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

3

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

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

可以正常工作(由Tom提供)。但是,这并非万无一失。如果提供以下文件名,它将不起作用:

image.jpg?foo=bar

它可能是一个有点矫枉过正,但我会使用URL解析器如建议这一个避免失败由于不可预测的文件名。

使用该特定功能,您可以得到如下文件名:

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

这将输出“ image.jpg”而不包含URL变量。然后,您可以自由获取文件扩展名。


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

3
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')

始终返回扩展名Lower cas,因此您可以在以下领域进行更改检查:

文件

文件(无扩展名)

文件。(无扩展名)


3

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

var file1 = "50.xsl";

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

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


1
美丽伴随简单。这是所有人最聪明,更优雅,更有效的答案。我一直使用String.substr(-3)或String.substr(-4)来获取基于Windows的系统上的扩展。为什么有人要为此使用正则表达式和疯狂循环。
asiby 2014年

13
@asiby这种解决方案是太空火箭发射后坠毁的主要原因。
VisioN

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>


3

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手动。

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


谁对节点说了什么?
香农·霍奇金斯

您不使用拆分或正则表达式的论点是包含插件或将应用程序与节点捆绑在一起,这是一项艰巨任务的最重要答案
Shannon Hochkins

@ShannonHochkins大多数情况下,无论如何您都会设置这些内容
sdgfsdh

@AndreiDraganescu我不希望它居高临下,所以已将其调低。
sdgfsdh

3

“一个班轮”使用得到的文件名和扩展名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"
// }

这在IE 11中不起作用
Gokul Maha,

您可以使用babel /打字稿/ polyfills来缺少IE 11的ES7 +功能
boehm_s

2

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

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

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

(1)如果文件没有扩展名,它将仍然返回文件名。(2)如果URL中有一个片段,但没有查询(例如page.html#fragment),则将返回文件扩展名和该片段。
杰克

2

这个简单的解决方案

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


1

Wallacer的回答很好,但是还需要再检查一次。

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

试试这个:

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

1

不要忘记某些文件没有扩展名,因此:

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

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

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

2
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
Brett DeWoody
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.