JavaScript - 如何从文件输入控件中提取文件名

164

当用户在网页中选择文件时,我希望能够仅提取文件名。

我尝试过使用 str.search 函数,但是当文件名类似于c:\uploads\ilike.this.file.jpg时,它似乎会失败。

我们如何提取没有扩展名的文件名呢?

15个回答

248

要拆分字符串({filepath}/{filename})并获取文件名,可以使用以下代码:

str.split(/(\\|\/)/g).pop()

"pop() 方法会删除数组的最后一个元素,并返回该元素的值给调用者。"
Mozilla 开发者网络

例子:

从:"/home/user/file.txt".split(/(\\|\/)/g).pop()

你会得到:"file.txt"


9
你也可以仅使用正则表达式而不进行任何数组操作来完成这个任务:var filename = filepath.replace(/^.*?([^\\\/]*)$/, '$1'); - vog
1
vog的答案非常接近于这个问题的100%准确答案(除了需要去掉扩展名)。文件名与任何其他字符串没有区别。 - Jon Watte
2
分割正则表达式可以缩短为 [\\/]。此外,还要求去除文件扩展名。完整的解决方案请参见:https://dev59.com/s3RA5IYBdhLWcg3wsgPq#32156800 - vog
1
多平台,简洁。非常好。 - Marc
很棒的解决方案,我不明白它是如何工作的,这就是为什么我更喜欢它! - Chatoxz
我认为 (\\|\/) 的“长”正则表达式版本(而不是短的 [\\/])可以处理不同操作系统上的不同路径名语法,对吗?在 Windows 上是 C:\path\Filename.ext,在 Linux 和 macOS 上是 home/path/Filename.ext - wnm

174

现在有一种更简单的方法:

var fileInput = document.getElementById('upload');   
var filename = fileInput.files[0].name;

12
在调用.name之前,检查fileInput.files.length以防用户点击了取消。 - marcovtwout

150
假设您的文件上传有一个id为upload,那么以下代码应该能够解决问题:
var fullPath = document.getElementById('upload').value;
if (fullPath) {
    var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/'));
    var filename = fullPath.substring(startIndex);
    if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0) {
        filename = filename.substring(1);
    }
    alert(filename);
}

谢谢,这似乎很有效,但我只想要没有扩展名的文件名。在上面的代码中我该怎么做? - Yogi Yang 007
我添加了以下两行代码来提取没有扩展名的文件名: "filename = filename.substring(0,filename.length-4); filename = filename.toLowerCase();" - Yogi Yang 007
14
瑜伽杨说,不要用那种方法。相反,应该使用:filename = filename.substring(0, filename.lastIndexOf('.')); 因为他的方法无法处理扩展名超过3个字符的文件,例如:.html、.jpeg等。 - Yeti
1
如何在选择多个文件时获取文件名? - avngr
为什么不这样计算startIndex呢?var startIndex = Math.max(fullPath.lastIndexOf('\\'), fullPath.lastIndexOf('/')) + 1; - nollidge

45

非常简单

let file = $("#fileupload")[0].files[0]; 
file.name

如果您正在使用TypeScript,则可以使用以下代码获取文件上传控件的第一个文件:$("#fileupload")[0]["files"][0]; - Morvael
这在2022年有效。FWIW - Joe Johnston

29

假设:

<input type="file" name="file1" id="theFile">

JavaScript代码将是:

var fileName = document.getElementById('theFile').files[0].name;

9

我猜你想去掉所有的扩展名,比如将/tmp/test/somefile.tar.gz变成somefile

使用正则表达式的直接方法:

var filename = filepath.match(/^.*?([^\\/.]*)[^\\/]*$/)[1];

使用正则表达式和数组操作的替代方法:

var filename = filepath.split(/[\\/]/g).pop().split('.')[0];

1
这并没有像要求的那样去掉扩展名。 - Jon Watte
已解决。感谢提示! - vog

8
var pieces = str.split('\\');
var filename = pieces[pieces.length-1];

这假设用户正在运行Windows操作系统。其他操作系统使用不同的文件路径分隔符。 - Quentin
你需要为非Windows用户检查'/'字符吗?例如:if (!pieces) { str.split('/'); }?虽然这是一个简单的好方法,但是+1。 - Ian Oxley
如果我没记错的话,IE是唯一一个无论如何都会给出文件的完整路径的浏览器...你不需要在其他浏览器上像Firefox那样进行分割,所以它仍然有效。虽然我承认我没有尝试过每个Linux/Unix浏览器。 - TM.
7
将字符串按照反斜杠或正斜杠进行分割,并返回分割后的数组。适用于Windows和Unix操作系统。 - Tracker1
@TM。Chrome出于安全考虑使用了假路径变量,这看起来不太好看;如果我没记错的话,这取决于您使用的操作系统。 - lededje
奇怪的是,只有Windows用户界面和编译器关心您在目录分隔符上使用“\”还是“/”。内部Win32和内核库将它们视为相同。 - Jesse Chisholm

6

输入: C:\path\Filename.ext
输出: Filename

在HTML代码中,将文件的onChange值设置为以下内容...

<input type="file" name="formdata" id="formdata" onchange="setfilename(this.value)"/>

假设您的文本框 ID 是 'wpName' ...
<input type="text" name="wpName" id="wpName">

JavaScript

<script>
  function setfilename(val)
  {
    filename = val.split('\\').pop().split('/').pop();
    filename = filename.substring(0, filename.lastIndexOf('.'));
    document.getElementById('wpName').value = filename;
  }
</script>

5
我刚刚制作了自己的版本。如果您不需要全部内容,那么我的函数可以用于提取您想要的任何内容,您可以轻松地删除一些代码。
<html>
<body>
<script type="text/javascript">
// Useful function to separate path name and extension from full path string
function pathToFile(str)
{
    var nOffset = Math.max(0, Math.max(str.lastIndexOf('\\'), str.lastIndexOf('/')));
    var eOffset = str.lastIndexOf('.');
    if(eOffset < 0 && eOffset < nOffset)
    {
        eOffset = str.length;
    }
    return {isDirectory: eOffset === str.length, // Optionally: && nOffset+1 === str.length if trailing slash means dir, and otherwise always file
            path: str.substring(0, nOffset),
            name: str.substring(nOffset > 0 ? nOffset + 1 : nOffset, eOffset),
            extension: str.substring(eOffset > 0 ? eOffset + 1 : eOffset, str.length)};
}

// Testing the function
var testcases = [
    "C:\\blabla\\blaeobuaeu\\testcase1.jpeg",
    "/tmp/blabla/testcase2.png",
    "testcase3.htm",
    "C:\\Testcase4", "/dir.with.dots/fileWithoutDots",
    "/dir.with.dots/another.dir/"
];
for(var i=0;i<testcases.length;i++)
{
    var file = pathToFile(testcases[i]);
    document.write("- " + (file.isDirectory ? "Directory" : "File") + " with name '" + file.name + "' has extension: '" + file.extension + "' is in directory: '" + file.path + "'<br />");
}
</script>
</body>
</html>

将输出以下内容:
  • 名为“testcase1”的文件扩展名为:“jpeg”,位于目录:“C:\ blabla \ blaeobuaeu”中
  • 名为“testcase2”的文件扩展名为:“png”,位于目录:“/ tmp / blabla”中
  • 名为“testcase3”的文件扩展名为:“htm”,位于目录:“”中
  • 名为“Testcase4”的目录扩展名为:“”,位于目录:“C:”中
  • 名为“fileWithoutDots”的目录扩展名为:“”,位于目录:“/ dir.with.dots”中
  • 名为“”的目录扩展名为:“”,位于目录:“/ dir.with.dots / another.dir”中
isDirectory中添加&& nOffset+1 === str.length后,将输出以下内容:
  • 名为“testcase1”的文件扩展名为:“jpeg”,位于目录:“C:\ blabla \ blaeobuaeu”中
  • 名为“testcase2”的文件扩展名为:“png”,位于目录:“/ tmp / blabla”中
  • 名为“testcase3”的文件扩展名为:“htm”,位于目录:“”中
  • 名为“Testcase4”的目录扩展名为:“”,位于目录:“C:”中
  • 名为“fileWithoutDots”的目录扩展名为:“”,位于目录:“/ dir.with.dots”中
  • 名为“”的目录扩展名为:“”,位于目录:“/ dir.with.dots / another.dir”中
通过给出的测试用例,可以看到此函数与其他提出的方法相比具有很强的鲁棒性。
对于新手的注意事项:\\是转义字符,例如\n表示换行,\t表示制表符。要写出\n,您必须实际键入\\n。

1
注意这个路径:dir.with.dots/fileWithoutDots,因为你会得到比nOffset小的eOffset并且混淆提取表达式。 - Jesse Chisholm
好的,已经修复了。现在应该也能正常工作了(添加了 && eOffset < nOffset)。 - Yeti

3

Easy Path:

JQuery

$("#fileInputId").on("change", () => {
    alert($("#fileInputId")[0].files[0].name);
});

JavaScript

document.getElementById("fileInputId").onchange = function() {
   alert(document.getElementById("fileInputId").files[0].name)
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接