Node.js获取文件扩展名

321

我正在使用express 3和node.js创建一个文件上传函数。

我想获取图片的文件扩展名,以便可以将文件重命名,然后将文件扩展名附加到文件名中。

app.post('/upload', function(req, res, next) {
    var is = fs.createReadStream(req.files.upload.path),
        fileExt = '', // I want to get the extension of the image here
        os = fs.createWriteStream('public/images/users/' + req.session.adress + '.' + fileExt);
});

如何在 Node.js 中获取图像的文件扩展名?


1
https://dev59.com/TGkv5IYBdhLWcg3wqiqS 重复? - bill automata
4
那个问题不是关于MIME类型的吗?我想要文件扩展名。 - georgesamper
16个回答

681

我相信你可以通过以下方式获取文件名的扩展名。

var path = require('path')

path.extname('index.html')
// returns
'.html'

如果您想在文件名中获取所有扩展名(例如,filename.css.gz => css.gz),请尝试以下方法:

const ext = 'filename.css.gz'
  .split('.')
  .filter(Boolean) // removes empty extensions (e.g. `filename...txt`)
  .slice(1)
  .join('.')

console.log(ext) // prints 'css.gz'

69
请注意,它只会获取最后一个点之后的字符,因此像app.css.gz这样的文件名称只会返回.gz而不是.css.gz,这可能是您想要的,也可能不是。 - xentek
23
在这种情况下,只需使用 filename.split('.').pop(); - Aamir Afridi
13
这会返回相同的字符串,只是没有了 . - Ram
16
尝试使用'filename.css.gz'.split('.').slice(1).join('.')来获取所有扩展名。 - Trevor
19
通常情况下,文件后缀是最后出现的。例如,当我们期望有多个后缀时(例如 tar.gz),最好检查它是否在最后出现。可以使用正则表达式,如“tar.gz$”,也可以构建一个函数来实现此功能,从结尾开始检查并逐步向前匹配。这样你就能拥有一个检查文件后缀的函数了。为什么呢?因为对于像 jone.lastTest.654654556.tar.gz 这样的文件,期望的后缀是 tar.gz,但如果应用任何只考虑第一个点之前的内容的函数,将无法正确处理。 - Mohamed Allal
显示剩余6条评论

42

更新:

自原回答以来,path模块中已添加了extname()函数,请参见Snowfish的回答。

原回答:

我正在使用此函数来获取文件扩展名,因为我没有找到更简单的方法(但我认为这是可能的):

function getExtension(filename) {
    var ext = path.extname(filename||'').split('.');
    return ext[ext.length - 1];
}

你必须使用'require 'path''才能使用它。

另一种不使用path模块的方法:

function getExtension(filename) {
    var i = filename.lastIndexOf('.');
    return (i < 0) ? '' : filename.substr(i);
}

4
可以。我觉得有更简单的方法可以使用node来完成。这是我的做法:var is = fs.createReadStream(req.files.upload.path), fileType = is.path.split(/[. ]+/).pop(); - georgesamper
6
正如@Snowfish的回答所指出的那样,你应该真的只使用path模块而不是编写自己的模块。更多信息:http://nodejs.org/api/path.html#path_path_extname_p - xentek
1
当文件没有显示扩展名时怎么办? - oldboy

27
// you can send full url here
function getExtension(filename) {
    return filename.split('.').pop();
}
如果您正在使用 Express,请在配置中间件(bodyParser)时添加以下行:
app.use(express.bodyParser({ keepExtensions: true}));

18

使用substr()方法比使用split()pop()更为高效。

请参考此处的性能差异:http://jsperf.com/remove-first-character-from-string

// returns: 'html'
var path = require('path');
path.extname('index.html').substr(1);

输入图像描述

2019年8月更新 如评论中@xentek所指出; substr()现在被认为是一个遗留函数(MDN文档)。你可以使用substring()代替。 substr()substring()之间的区别在于,substr()的第二个参数是返回的最大长度,而substring()的第二个参数是要停止的索引(不包括该字符)。此外,substr()接受负数起始位置作为从字符串末尾的偏移量,而substring()则不接受。


1
现在针对 substr 有一个警告,它被认为是一种过时的函数,如果可能的话应该避免使用 - 更多信息请看 MDN - Core972
1
在进行 substr(1) 测试时,您还应考虑用于 path.extname 的时间。 - eugenekr

15

这个解决方案支持查询字符串!

var Url = require('url');
var Path = require('path');

var url = 'http://i.imgur.com/Mvv4bx8.jpg?querystring=true';
var result = Path.extname(Url.parse(url).pathname); // '.jpg'

9

你可以使用 path.parse(path),例如

const path = require('path');
const { ext } = path.parse('/home/user/dir/file.txt');

7
一种简单的解决多个点拓展问题的方法,无需require:
var filename = 'file.with.long.extension';
var ext = filename.substring(filename.indexOf('.')); 
//ext = '.with.long.extension'

如果您不想要前导点,则可以这样做:
var filename = 'file.with.long.extension';
var ext = filename.substring(filename.indexOf('.')+1); 
//ext = 'with.long.extension'

请确保测试文件是否有扩展名。


6

导入 extname 以返回文件的扩展名:

import { extname } from 'path';
extname(file.originalname);

其中file是表单中的文件“名称”


4

我认为在请求中映射 Content-Type 头部也可以行得通。即使上传的文件没有扩展名也可以正常工作。 (当请求中的文件名没有扩展名时)

假设你是使用 HTTP POST 发送数据:

POST /upload2 HTTP/1.1
Host: localhost:7098
Connection: keep-alive
Content-Length: 1047799
Accept: */*
Origin: http://localhost:63342
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,    like Gecko) Chrome/51.0.2704.106 Safari/537.36
Content-Type: multipart/form-data; boundary=----   WebKitFormBoundaryPDULZN8DYK3VppPp
Referer: http://localhost:63342/Admin/index.html? _ijt=3a6a054pasorvrljf8t8ea0j4h
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,az;q=0.6,tr;q=0.4
Request Payload
------WebKitFormBoundaryPDULZN8DYK3VppPp
Content-Disposition: form-data; name="image"; filename="blob"
Content-Type: image/png


------WebKitFormBoundaryPDULZN8DYK3VppPp--

这里的名称Content-Type头包含数据的mime类型。将此mime类型映射到扩展名可获得文件扩展名 :)。
Restify BodyParser会将此标头转换为一个名为type的属性。
File {
  domain: 
   Domain {
     domain: null,
     _events: { .... },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [ ... ] },
  _events: {},
  _eventsCount: 0,
  _maxListeners: undefined,
  size: 1047621,
  path: '/tmp/upload_2a4ac9ef22f7156180d369162ef08cb8',
  name: 'blob',
  **type: 'image/png'**,
  hash: null,
  lastModifiedDate: Wed Jul 20 2016 16:12:21 GMT+0300 (EEST),
  _writeStream: 
  WriteStream {
   ... },
     writable: true,
     domain: 
     Domain {
        ...
     },
      _events: {},
      _eventsCount: 0,
     _maxListeners: undefined,
     path: '/tmp/upload_2a4ac9ef22f7156180d369162ef08cb8',
     fd: null,
     flags: 'w',
     mode: 438,
     start: undefined,
     pos: undefined,
     bytesWritten: 1047621,
     closed: true } 
}

您可以使用此标题并手动执行扩展名映射(子字符串等...),但也有现成的库可供使用。当我进行谷歌搜索时,以下两个是最佳结果:
  • mime
  • mime-types
它们的使用也很简单:
 app.post('/upload2', function (req, res) {
  console.log(mime.extension(req.files.image.type));
 }

上面的代码片段将在控制台打印出 png

3

一个扩展 String.prototype 的一行代码:

Object.defineProperty(String.prototype, "ext", {get: function(x) {return this.split('.').pop()}})
str = 'fox.fbx';
str.ext

结果:

这里输入图片描述


(注:此内容为HTML代码,仅供参考)

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