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

Ser*_*Amo 457 javascript file-extension

看代码:

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

function getFileExtension(filename) {
    /*TODO*/
}
Run Code Online (Sandbox Code Playgroud)

wal*_*cer 784

return filename.split('.').pop();
Run Code Online (Sandbox Code Playgroud)

把事情简单化 :)

编辑:

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

return filename.substring(filename.lastIndexOf('.')+1, filename.length) || filename;
Run Code Online (Sandbox Code Playgroud)

VisioN的答案可以更好地处理一些极端情况,特别是没有扩展名的文件(.htaccess包括其他内容).

它非常高效,并且在""点之前没有点或没有字符串时返回而不是完整的字符串,以可以说是更好的方式处理角落情况.这是一个非常精心设计的解决方案,虽然难以阅读.将它粘贴在你的助手lib中,然后使用它.

旧编辑:

如果您要运行没有扩展名的文件或没有扩展名的隐藏文件(请参阅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
Run Code Online (Sandbox Code Playgroud)

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

如果a[0] === ""a.length === 2它是一个隐藏的文件不带扩展名即.的.htaccess

希望这有助于解决稍微复杂的案例中的问题.在性能方面,我相信这个解决方案大多数浏览器中的正则表达式慢一点.但是,出于最常见的目的,此代码应该是完全可用的.

  • 在这种情况下,输出是"jpg" (19认同)
  • 但在这种情况下,文件名看起来像filname.tes.test.jpg.请考虑输出.我希望这是假的. (6认同)
  • 我不能评论性能,但这个看起来一定很干净!我正在使用它.+1 (4认同)
  • @wallacer:如果`filename`实际上没有扩展名怎么办?这不会简单地返回基本文件名,这有点不好吗? (2认同)

Tom*_*Tom 720

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


编辑:只是因为这是接受的答案; wallacer的答案确实要好得多:

return filename.split('.').pop();
Run Code Online (Sandbox Code Playgroud)

我的回答是:

return /[^.]+$/.exec(filename);
Run Code Online (Sandbox Code Playgroud)

应该这样做.

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

return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;
Run Code Online (Sandbox Code Playgroud)

  • 以下评价很高的答案要好得多. (5认同)
  • 两次执行正则表达式不是很贵吗? (3认同)
  • 所有可能的情况都按如下方式处理:return filename.split(".").slice(1).pop()|| ""; (3认同)
  • 不幸的是,两个解决方案都失败了,例如*file*和*.htaccess*. (2认同)

Vis*_*ioN 273

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

 return fname.slice((fname.lastIndexOf(".") - 1 >>> 0) + 2);
Run Code Online (Sandbox Code Playgroud)

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

 return fname.slice((Math.max(0, fname.lastIndexOf(".")) || Infinity) + 1);
Run Code Online (Sandbox Code Playgroud)

两者都可以正常使用没有扩展名的名称(例如myfile)或以.dot开头(例如.htaccess):

 ""                            -->   ""
 "name"                        -->   ""
 "name.txt"                    -->   "txt"
 ".htpasswd"                   -->   ""
 "name.with.many.dots.myext"   -->   "myext"
Run Code Online (Sandbox Code Playgroud)

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

速度比较

简短的如何运作:

  1. String.lastIndexOfmethod返回"."给定字符串(即fname)中子字符串(即)的最后位置.如果找不到子字符串,则返回方法-1.
  2. 文件名中点的"不可接受"位置是-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"
Run Code Online (Sandbox Code Playgroud)

所有这三种变体都可以在客户端的任何Web浏览器中使用,也可以在服务器端NodeJS代码中使用.

  • @mrbrdo根据问题的要求,此方法不应仅使用文件名的完整路径.在downvoting之前仔细阅读问题. (31认同)
  • 为什么要尽力优化这么简单的代码?在JavaScript中很少见到Tilde和bitshift运算符,我无法支持这样的答案.如果需要5个要点来解释1行代码是如何工作的,那么最好重写代码,这样它实际上是可以理解的. (8认同)
  • @Jackson考虑到这是一个为问题提供多种解决方案的站点,拥有一个优化性能的解决方案从来都不是坏事.您声明"在任何应用程序中都不会产生任何明显的差异"完全基于您可能使用的可能应用程序的狭窄范围.除此之外,它可能会让某人在查看问题时可以优化一些学习体验他们需要为他们正在编写的计算密集型应用程序制作的其他代码. (7认同)
  • 这一行的速度在任何应用中都不会产生明显的差异.Bitwise很少被使用,像JSLint和JSHint这样的流行链接警告不要使用它们.对这种逻辑的性能和紧凑性的痴迷降低了代码的质量; 如果代码需要"额外调查",我认为它"不好". (6认同)
  • 不行."/home/user/.app/config"返回"app/config",这是完全错误的. (5认同)
  • 他从来没有明确地说过这一点,而且如果它在路径上工作,它会更有用 (5认同)
  • @vog如果您不喜欢这些代码或者发现它没用,您可以自由使用另一个代码或实现您自己的更简单的解决方案,该解决方案可以使用不同的输入正常工作.我个人觉得这个解决方案可行,对我的需求很有帮助.此外,我没有看到任何问题,阅读它的工作原理的描述或只是忽略它,如果你不理解它.是否使用是你的决定,我只是分享了一些有用的东西. (4认同)
  • @Jackson 1)如果你没有在JavaScript代码中看到或使用波浪号和bitshift运算符,那么我就有坏消息.2)如果您总是接受并使用您理解的代码而不进行任何额外调查,那么我也有坏消息.如果你不理解困难的代码,它并不总是意味着代码是坏的.在当前示例中,很明显这段代码的工作速度比任何其他替代方案快很多倍,这使其非常适合在批量操作中使用.使其紧凑也很重要.还有一个想要学习的人的描述. (3认同)
  • 太棒了!为什么这不是答案#1? (3认同)
  • @BennyNeugebauer但是如果你需要排除这个规则,只需使用`fname.substr((fname.lastIndexOf(".")>>> 0)+ 1)`而不是:) (2认同)
  • @VisioN这里的一般问题是一个简单的任务应该有一个简单的解决方案.如果没有,很难判断是否有微妙的错误.如果您需要其他人多次阅读您的代码才能理解其工作原理,并且您的代码已满,那么任何人(甚至不是您自己)都不会在早期发现错误.你的团队注定会注定要追捕虫子.没有任何收获.基准测试令人分心,他们只是表明这种优化不值得麻烦,因为显而易见的解决方案已经比需要的更快. (2认同)
  • 我测试了_单行非正则表达式通用解决方案_,它在我的所有测试中都有效(与其他一些答案不同): `const t = ['./asdf.mz', '/asdf/qwer.maz', 'asdf. mm', 'sdf/qwer.ww', './.asdf.mz', '/asdf/.qwer.maz', '.asdf.mm', 'sdf/.qwer.ww', './asdf '、'/adsf/qwer'、'asdf'、'sdf/qewr'、'./.asdf'、'/adsf/.qwer'、'.asdf'、'sdf/.qewr']`。我像这样测试了它: ```t.forEach(file =&gt; {const filename = file.match(/[^\/]+$/g)?.[0]; console.log(`${file} : ${filename.slice((Math.max(0, filename.lastIndexOf(".")) || Infinity) + 1)}`)})```。 (2认同)

Phi*_*Lho 32

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

经过测试

"a.b"     (=> "b") 
"a"       (=> "") 
".hidden" (=> "") 
""        (=> "") 
null      (=> "")  
Run Code Online (Sandbox Code Playgroud)

"a.b.c.d" (=> "d")
".a.b"    (=> "b")
"a..b"    (=> "b")
Run Code Online (Sandbox Code Playgroud)


Dim*_*ima 19

function getExt(filename)
{
    var ext = filename.split('.').pop();
    if(ext == filename) return "";
    return ext;
}
Run Code Online (Sandbox Code Playgroud)

  • return(ext === filename)?'':分机; (6认同)
  • jpg.jpg或txt.txt会不会失败? (3认同)

sdg*_*sdh 16

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

import path from 'path';

console.log(path.extname('abc.txt'));
Run Code Online (Sandbox Code Playgroud)

输出:

。文本

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

path.extname('abc.txt').slice(1) // 'txt'
Run Code Online (Sandbox Code Playgroud)

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

path.extname('abc') // ''
Run Code Online (Sandbox Code Playgroud)

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

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

  • 谁说节点? (2认同)

Pon*_*ono 13

var extension = fileName.substring(fileName.lastIndexOf('.')+1);
Run Code Online (Sandbox Code Playgroud)


Jak*_*erg 10

如果您正在处理网址,则可以使用:

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
Run Code Online (Sandbox Code Playgroud)

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


Ran*_*ku' 8

var parts = filename.split('.');
return parts[parts.length-1];
Run Code Online (Sandbox Code Playgroud)


Joe*_*lla 8

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


Jac*_*ack 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
};
Run Code Online (Sandbox Code Playgroud)

测试

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

"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"
"..."                                                                       --> ""
Run Code Online (Sandbox Code Playgroud)

JSLint的

0警告.


mrb*_*rdo 6

快速并且可以正确使用路径

(filename.match(/[^\\\/]\.([^.\\\/]+)$/) || [null]).pop()
Run Code Online (Sandbox Code Playgroud)

一些边缘情况

/path/.htaccess => null
/dir.with.dot/file => null
Run Code Online (Sandbox Code Playgroud)

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

  • 就像我已经告诉过你的那样,从未明确说过,处理路径的解决方案显然更有用.关于SO问题的答案应该对提出问题的人以外的其他人有用.我真的不认为处理输入超集的解决方案应该被低估. (3认同)
  • downvote是使用带有`.exec()`的全局变量.你的代码会更好``(filename.match(/[^\\/]\.([^\\/.]+)$/)|| [null]).pop()`. (3认同)

boe*_*m_s 6

“one-liner”使用数组解构来获取文件名和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});
Run Code Online (Sandbox Code Playgroud)

具有更好的缩进:

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"
// }
Run Code Online (Sandbox Code Playgroud)


小智 5

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;
}
Run Code Online (Sandbox Code Playgroud)

//用法

扩展名('文件.jpeg')

始终返回扩展名 lower cas,以便您可以在字段更改中检查它适用于:

文件.JpEg

文件(无扩展名)

文件。(无扩展名)


Hus*_*zal 5

我只是想分享这个。

fileName.slice(fileName.lastIndexOf('.'))
Run Code Online (Sandbox Code Playgroud)

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

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


Vit*_*.us 5

这个简单的解决方案

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

测试

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


Jam*_*Jr. 5

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

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

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

不要过于自信,或者吹我自己的小号,但我还没有看到任何用于此任务的代码块(在一系列不同的输入参数中找到“正确”的文件扩展名function),它的工作原理与此相同。

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

它需要两个参数:

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

  • Boolean: 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;
    };
Run Code Online (Sandbox Code Playgroud)

享受!你太客气了!:


山茶树*_*葡萄树 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"));
Run Code Online (Sandbox Code Playgroud)


Mat*_*vic 5

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

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