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个回答

1
const path = require('path');

function getExt(str) {
  const basename = path
    .basename(str)
    // Patch: for hidden files
    // Removes all dots at the beginning of a line
    .replace(/^(\.+)/i, '');

  const firstDot = basename.indexOf('.');
  const lastDot = basename.lastIndexOf('.');
  const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1');

  if (firstDot === lastDot) {
    return extname;
  }

  return basename.slice(firstDot, lastDot) + extname;
}

const files = [
  '/home/charlike/bar/.hidden.tar.gz~',     // ".tar.gz"
  '/home/charlike/bar/file.tar.gz~',        // ".tar.gz"
  '/home/charlike/bar/file.tar.gz+cdf2',    // ".tar.gz"
  '/home/charlike/bar/file.tar.gz?quz=zaz', // ".tar.gz"
];

const fileAndExt = files.map((file) => [ file, getExt(file) ]);

console.log(JSON.stringify(fileAndExt, null, 2));

1
感谢您提供这段代码片段,它可能会为一些具体问题提供一些有限的帮助。适当的解释会大大提高其长期价值,说明这为何是一个好的问题解决方法,并使其对未来有类似问题的读者更加有用。请编辑您的答案,添加一些解释,包括您所做出的假设。 - Giorgio Tempesta

1

path.extname在大多数情况下可以解决问题。但是,它会包括最后一个.之后的所有内容,包括http请求的查询字符串和哈希片段:

var path = require('path')
var extname = path.extname('index.html?username=asdf')
// extname contains '.html?username=asdf'

在这种情况下,您需要尝试类似于以下内容:
var regex = /[#\\?]/g; // regex of illegal extension characters
var extname = path.extname('index.html?username=asdf');
var endOfExt = extname.search(regex);
if (endOfExt > -1) {
    extname = extname.substring(0, endOfExt);
}
// extname contains '.html'

请注意,具有多个句点的扩展名(例如.tar.gz)将无法与path.extname一起正常工作。

1
var fileName = req.files.upload.name;

var arr = fileName.split('.');

var extension = arr[length-1];

1
长度变量从哪里来? - Angel S. Moreno
3
尝试在你的回答中添加一些解释。这样,原帖作者实际上可以理解你做了什么以及为什么这样做。这样原帖作者就可以从你的回答中学习,而不仅仅是复制/粘贴它。 - Oldskool

0

试一下这个

const path = require('path');

function getExt(str) {
  const basename = path.basename(str);
  const firstDot = basename.indexOf('.');
  const lastDot = basename.lastIndexOf('.');
  const extname = path.extname(basename).replace(/(\.[a-z0-9]+).*/i, '$1');

  if (firstDot === lastDot) {
    return extname;
  }

  return basename.slice(firstDot, lastDot) + extname;
}

// all are `.gz`
console.log(getExt('/home/charlike/bar/file.gz'));
console.log(getExt('/home/charlike/bar/file.gz~'));
console.log(getExt('/home/charlike/bar/file.gz+cdf2'));
console.log(getExt('/home/charlike/bar/file.gz?quz=zaz'));

// all are `.tar.gz`
console.log(getExt('/home/charlike/bar/file.tar.gz'));
console.log(getExt('/home/charlike/bar/file.tar.gz~'));
console.log(getExt('/home/charlike/bar/file.tar.gz+cdf2'));
console.log(getExt('/home/charlike/bar/file.tar.gz?quz=zaz'));


很遗憾,如果文件名包含像 2023-02-16 14.04.43.jpg 这样的点,它就无法工作。 - undefined

0

使用path并不是非常可靠,因为它取决于文件名中是否包含扩展名,而这并不总是情况。

你应该使用file-type package,它通过检查缓冲区的魔数来检测扩展名,而不是依赖于文件名,因为文件名并不总是包含扩展名。


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0
以下函数将字符串分割并返回名称和扩展名,无论扩展名中有多少个点。如果没有扩展名,则返回空字符串。以点和/或空格开头的名称也可以使用。
function basext(name) {
  name = name.trim()
  const match = name.match(/^(\.+)/)
  let prefix = ''
  if (match) {
    prefix = match[0]
    name = name.replace(prefix, '')
  }
  const index = name.indexOf('.')
  const ext = name.substring(index + 1)
  const base = name.substring(0, index) || ext
  return [prefix + base, base === ext ? '' : ext]
}

const [base, ext] = basext('hello.txt')

如果文件名包含像2023-02-16 14.04.43.jpg这样的点,或者其他字符像file.gz~file.gz+cdf2,就无法工作,正如这个答案中的示例所示,虽然不确定它们是否有意义,但根据这个维基页面,有很多特殊字符可能会出现,比如--++# - undefined

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