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

看代码:

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


function getFileExtension(filename) {
/*TODO*/
}
766739 次浏览
return filename.replace(/\.([a-zA-Z0-9]+)$/, "$1");

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

自从这个问题最初发布以来,很多事情都发生了变化——在Wallacer修改后的答案VisioN的出色分解中有很多非常好的信息


因为这是公认的答案;华莱士的回答确实更好:

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

我以前的回答是:

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

应该这么做。

针对PhiLho的评论,可以这样回复:

return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : undefined;
var parts = filename.split('.');
return parts[parts.length-1];
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")
function file_get_ext(filename)
{
return typeof filename != "undefined" ? filename.substring(filename.lastIndexOf(".")+1, filename.length).toLowerCase() : false;
}

我刚刚意识到,对p4bl0的回答发表评论是不够的,尽管Tom的回答显然解决了问题:

return filename.replace(/^.*?\.([a-zA-Z0-9]+)$/, "$1");
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”)

总是返回扩展低cas,所以你可以检查它的字段变化 适用于:< / p >

file.JpEg

文件(无扩展名)

文件。(noextension)

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");
}
}
return filename.split('.').pop();

编辑:

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

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

下面的视觉的回答可以更好地处理一些极端情况,特别是没有扩展名的文件(包括.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,它是一个没有扩展名ie的可见文件。# EYZ1

如果a[0] === ""a.length === 2是一个隐藏文件,没有扩展名ie。# EYZ2

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

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

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

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

image.jpg?foo=bar

这可能有点过分,但我建议使用url解析器,如这一个,以避免由于不可预测的文件名而导致的失败。

使用这个特定的函数,你可以得到这样的文件名:

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

这将输出“image.jpg”,不带url变量。然后您就可以获取文件扩展名了。

试试这个:

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;
}
function getExt(filename)
{
var ext = filename.split('.').pop();
if(ext == filename) return "";
return ext;
}
var extension = fileName.substring(fileName.lastIndexOf('.')+1);

下面的解决方案是足以用于批量操作并节省额外的字节:

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

下面是另一个单行非regexp通用解决方案:

 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. “unacceptable"点在文件名中的位置是-10,它们分别指没有扩展名的名称(例如"name")和以点开头的名称(例如".htaccess")。
  3. 零填充右移位运算符 (>>>)如果与零一起使用,则会影响负数将-1转换为4294967295-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代码中使用。

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

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

试试这个:

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

别忘了有些文件没有扩展名,所以:

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

快速和正确的路径工作

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

一些边缘情况

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

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

我只是想分享这个。

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

,尽管这有一个缺点,没有扩展名的文件将返回最后一个字符串。 但如果你这样做,这将修复所有的事情:

   function getExtention(fileName){
var i = fileName.lastIndexOf('.');
if(i === -1 ) return false;
return fileName.slice(i)
}
var filetypeArray = (file.type).split("/");
var filetype = filetypeArray[1];

在我看来,这是一个更好的方法。

如果你正在寻找一个特定的扩展,并且知道它的长度,你可以使用字符串的子串:

var file1 = "50.xsl";


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

# EYZ0 # EYZ1

我已经晚了很多个月,但为了简单起见,我使用了这样的东西

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

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

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

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

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


// Example
// some.url.com/with.in/&ot.s/files/file.jpg?spec=1&.ext=jpg
// jpg
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

代码

/**
* 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的警告。

这个简单的解决方案

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

我相信将来会有人缩小和/或优化我的代码。但是,作为现在,我有200%的信心,我的代码在每一个独特的情况下工作(例如,只有仅限文件名相对root-relative绝对的URL, 片段 #标签,查询 ?字符串,以及其他任何你可能决定扔在它),完美无缺,精确无误。

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

下面是JSFiddle: https://jsfiddle.net/JamesAndersonJr/ffcdd5z3/

不要过于自信,或者自吹自擂,但我还没有看到这个任务的任何代码块(在一组不同的function输入参数中找到“正确”文件扩展名)工作得这么好。

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

它有两个参数:

  • < p > # EYZ0 # EYZ1

  • 布尔:< em > < / em > showUnixDotFiles(是否显示以点"; "开头的文件)

如果你喜欢我的代码,一定要把它添加到你的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;
};

享受吧!不客气!:

如果你正在处理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

演示:# EYZ0

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

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

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

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

import path from 'path';


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

输出:

. txt

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

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

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

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

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

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

使用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"
// }

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

我知道这是一个老问题,但我写了这个函数的测试提取文件扩展名,她可用的NPM, Yarn, Bit 也许它会帮助别人。
# EYZ0 < / p >
function getFileExtension(path: string): string {
var regexp = /\.([0-9a-z]+)(?:[\?#]|$)/i
var extension = path.match(regexp)
return extension && extension[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

试试这是一行代码

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

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