Node.js - 文件系统获取文件类型,2012年的解决方案。

33
我需要使用Node.js来获取文件的文件类型,以便设置内容类型。我知道可以轻松地检查文件扩展名,但我也有没有扩展名的文件,它们应该具有内容类型image/pngtext/html
这是我的代码(我知道它没有太多意义,但这是我需要的基础):
var http = require("http"),
    fs = require("fs");
http.createServer(function(req, res) {
    var data = "";
    try {
        /*
         * Do not use this code!
         * It's not async and it has a security issue.
         * The code style is also bad.
         */
        data = fs.readFileSync("/home/path/to/folder" + req.url);
        var type = "???"; // how to get the file type??
        res.writeHead(200, {"Content-Type": type});
    } catch(e) {
        data = "404 Not Found";
        res.writeHead(404, {"Content-Type": "text/plain"});
    }
    res.write(data);
    res.end();
}).listen(7000);

我在API中没有找到相应的功能,那么我该如何做呢?

8
每次请求都使用readFileSync?听起来不是一个好主意... - ThiefMaster
4
正如他所说,这只是虚拟代码(至少我认为“我知道这没有多大意义,但那是我需要的基础”的意思)。 - Daniel Baulig
8个回答

46

有一个帮助库用于查找MIME类型:Mime

var mime = require('mime');

mime.getType('/path/to/file.txt'); // => 'text/plain'

但它仍然使用扩展进行查找。

4
实际上,那个库非常好,但正如ThiefMaster所评论的那样,它是基于文件扩展名的,因此它会下载没有扩展名的文件。 - noob
3
这对我没有用,mime.lookup不是一个函数(可能已被删除)。 - Andrea Girardi
3
自版本2开始,“lookup”已更名为“getType”。来源:https://www.npmjs.com/package/mime - Bielik
当我从表单上传文件时,它没有扩展名。而且扩展名本来就不可靠。 - iPhoney

20

看一下mmmagic模块。它是一个libmagic绑定,似乎正好符合您的要求。


4
假设fs.stat的作用与stat相同:那么从中获取到的任何信息如何帮助他确定文件的MIME类型? - ThiefMaster
2
我其实不知道,我猜它会告诉你一些有用的信息 :P - Raynos
11
@Raynos:既然你一无所知,为什么要发表评论?这是迄今为止最好的答案。 - Asherah
2
尝试将魔法文件的路径作为第一个参数传递给 new Magic() - ThiefMaster
有没有办法从通过管道移动的文件中获取MIME类型,而不需要在文件系统中有底层文件?我看到这个API提供了一种从缓冲区获取它的方法,但这似乎太过笨重,因为这似乎需要整个文件存在,而通常只需要检查文件的前几个字节。 - Michael

9

您应该看一下命令行工具file(Linux)。它会根据文件的前几个字节猜测文件类型。您可以使用child_process.spawn在Node中运行它。


6

您想查找MIME类型,幸运的是,Node有一个非常方便的库:

https://github.com/bentomas/node-mime#readme

编辑:

你可能需要考虑使用静态资源服务器,而不是自己设置这些内容。你可以使用 express 来轻松实现这一点,或者使用许多静态文件模块,例如 ecstatic。另一方面,你可能应该使用 nginx 来提供静态文件。


7
根据他想做什么,根据文件名获取类型可能不是最佳选择。 - ThiefMaster

4

2018年的解决方案

被采纳的答案似乎有Python依赖,其他答案要么过时,要么假设文件名具有某种扩展名。

请在这里找到我更加更新的答案。


1
这是最佳答案,应该是唯一的答案。很遗憾,这个六年前的问题被一个过时的答案困住了。@Stephen,如果我在一个新问题中问,你愿意回答吗? - xpt
当然可以 :) 我可以将这个答案链接到新的答案。 - Stephen Paul
这是链接,https://dev59.com/sLDma4cB1Zd3GeqPA8DI。谢谢@Stephen。 - xpt
很酷,我已经回答了。 - Stephen Paul

2
我使用了这个:
npm install mime-types

在代码内部:

var mime = require('mime-types');
tmpImg.contentType = mime.lookup(fileImageTmp);

其中,fileImageTmp是存储在文件系统上的图像副本(在此情况下为tmp)。

我能看到的结果是:image/jpeg


1
使用nodejs在2023年获取文件扩展名的方法如下,按照fp007的方法和file命令实用程序:
import { exec } from 'child_process'
import { promisify } from 'util'

// async exec, hell yes
const execPromise = promisify(exec)

// using the --brief flag would onmit the filepath in the output
// the --mime-type flag will output mime type strings
// the following command will only output the mimetype of the file
const { stdout: mimetype, stderr } = await execPromise(`file --brief --mime-type ${filepath}`)

console.log('mimetype: ', mimetype)
console.log('stderr: ', stderr)

来源:Node.js exec 的文档ss64 bash file 命令的文档


1
我认为最好的方法是使用系统的file命令,这样你就有三个优点:
  1. 没有依赖关系,
  2. 通过魔数确保文件的内容类型,
  3. 可以通过魔法文件创建内容类型。

例如:

let pathToFile = '/path/to/file';
const child_process = require('child_process');
child_process.exec(`"file" ${path}`, (err, res) => {
  let results = res.replace('\n', '').split(':');
  let stringPath = results[0].trim();
  let typeOfFile = results[1].trim();
  console.log(stringPath, typeOfFile);
});

Docs: https://www.man7.org/linux/man-pages/man1/file.1.html https://nodejs.org/docs/latest-v13.x/api/child_process.html#child_process_child_process_exec_command_options_callback


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