.NET 中的文件扩展名和 MIME 类型
我想从给定的扩展名获取 MIME 内容类型(最好不访问物理文件)。我已经看到了一些与此相关的问题,并且可以在以下位置恢复描述的执行此操作的方法:
- 使用 注册表信息。
- 使用 urlmon.dll 的 FindMimeFromData。
- 使用 IIS 信息。
- 推出您自己的 MIME 映射函数。例如,基于此表 。
我已经使用no.1有一段时间了,但我意识到注册表提供的信息并不一致,并且取决于机器上安装的软件。某些扩展名(例如 .zip)不用于指定内容类型。
解决方案 2 迫使我将文件放在磁盘上才能读取第一个字节,虽然速度很慢,但可能会得到很好的结果。
第三种方法基于目录服务和所有这些东西,这是我不太喜欢的方法,因为我必须添加 COM 引用,而且我不确定它在 IIS6 和 IIS7 之间是否一致。另外,我不知道这个方法的性能。
最后,我不想使用自己的表,但如果我想要平台(甚至 Mono)之间的结果具有良好的性能和一致性,那么最后似乎是最好的选择。
您认为有比使用我自己的表更好的选择还是其他描述的方法之一更好?你的经验是什么?
I want to get a MIME Content-Type from a given extension (preferably without accessing the physical file). I have seen some questions about this and the methods described to perform this can be resumed in:
- Use registry information.
- Use urlmon.dll's FindMimeFromData.
- Use IIS information.
- Roll your own MIME mapping function. Based on this table, for example.
I've been using no.1 for some time but I realized that the information provided by the registry is not consistent and depends on the software installed on the machine. Some extensions, like .zip don't use to have a Content-Type specified.
Solution no.2 forces me to have the file on disk in order to read the first bytes, which is something slow but may get good results.
The third method is based on Directory Services and all that stuff, which is something I don't like much because I have to add COM references and I'm not sure it's consistent between IIS6 and IIS7. Also, I don't know the performance of this method.
Finally, I didn't want to use my own table but at the end seems the best option if I want a decent performance and consistency of the results between platforms (even Mono).
Do you think there's a better option than using my own table or one of other described methods are better? What's your experience?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这取决于您需要 MIME 类型的用途。一般来说,对于服务(Web 应用程序、Web 服务等),建议不要使用依赖于操作系统设置的 MIME 列表,或者仅在无法找到 MIME 信息时作为后备。
我认为这也是 MS 选择将常量 MIME 类型放入其 System.Web.MimeMapping 类中的原因(不幸的是,无论出于何种原因,它是内部的)。
编辑:
包装器 (<= .NET 3.5)
包装器 (.NET 4.0)
.NET 4.5+
不需要包装器,调用公共方法
System.Web.MimeMapping.GetMimeMapping
。It depends what you need the MIME type for. In general, for services (web apps, web service, etc.), it's advisable not to use a MIME list which is dependent on the OS settings, or only as fallback if you cannot find MIME information otherwise.
I think that this is also the reason why MS chose to put constant MIME types in their
System.Web.MimeMapping
class (unfortunately it's internal, for whatever reason).Edit:
Wrapper (<= .NET 3.5)
Wrapper (.NET 4.0)
.NET 4.5+
No wrapper required, call the public method
System.Web.MimeMapping.GetMimeMapping
directly.我已将所有这些方法组合到我的实用程序库中,除了第 3 种方法。
顺便说一句,no.2(urlmon.dll)不需要静态文件,它只需要一些字节,无论它们来自哪里。
这是我当前的课程
}
I have combined all these approaches in my utility lib, except maybe no.3.
Btw, no.2 (urlmon.dll) doesn't require static file, it simply takes some bytes no matter where they had come from.
Here's my current class
}
System.Web.MimeMapping
有 3 个版本 - 两个版本 4.0(其中之一是内部版本),然后是也是内部版本 2.0。正如所指出的,在 .NET 4.5 框架的 System.Web 4.0 版中有一个该类的公共版本。对于 RoadkillWiki,我基本上对其进行了逆向工程,以节省每次反射的麻烦,Wiki 的文件处理程序默认情况下尝试使用 IIS/applicationhost.config,然后落入 MimeMapping 类:
和 MimeMapping:
The
System.Web.MimeMapping
has 3 versions - two version 4.0s (where one of these is internal), and then a version 2.0 which is also internal. As pointed out, there is a public version of the class in System.Web version 4.0 for the .NET 4.5 framework.For RoadkillWiki I've basically reverse engineered it to save the bother of reflecting each time, the Wiki's file handler tries to the use IIS/applicationhost.config by default, and then falls through to the MimeMapping class:
And MimeMapping:
我编写了一个程序来获取 Apache mime.types 文件并将其转换为按文件扩展名键入的 C#
Dictionary
。它在这里:https://github.com/cymen/ApacheMimeTypesToDotNet
实际输出是这个文件:
https://github.com/cymen/ApacheMimeTypesToDotNet/blob/master/ApacheMimeTypes.cs
希望其他人也发现它有用!
I've written a program to fetch and convert the Apache mime.types file to a C#
Dictionary<string, string>
keyed by file extension. It's here:https://github.com/cymen/ApacheMimeTypesToDotNet
The actual output is this file:
https://github.com/cymen/ApacheMimeTypesToDotNet/blob/master/ApacheMimeTypes.cs
Hopefully someone else finds it useful too!
Nisus - 您愿意将您的实用程序的完整源代码发布到某个地方吗?这真的很有帮助。谢谢!
没关系......
我编辑了 apache 定义文件,使其仅包含具有定义的扩展名的条目,然后扩展代码以在运行时从文本文件加载类型/扩展名。也许不太优雅,但肯定比为 mime 类型创建/维护 630 行源代码要好。
[在 MimeTypeCollection 的构造函数中而不是这个东西:
this.Add(new mimeTypeInfo("application/applixware",new List(new[] { ".aw" })));]
我还发现 Init() 方法会被调用,而 _extensions 和 _mime 成员不会已完全初始化,因此我将其更改为:
无论如何,我现在如何创建一个可以处理我需要的外部定义和本地注册表的类。
谢谢!
Nisus - would you be willing to post the entire source code for your utility somewhere? that would really be helpful. thanks!
Never mind....
I edited the apache definition file to only contain entries with defined extensions, then extended the code to load in the types/extensions from the text file at run time. Not elegant perhaps but sure beats creating/maintaining 630 lines of source code for the mime types.
[in the constructor for MimeTypeCollection instead of this stuff:
this.Add(new mimeTypeInfo("application/applixware",new List(new[] { ".aw" })));]
I also found that the Init() method would be called and the _extensions and _mime members would not be completely initialized so I changed it to read:
Anyway, I now how a class that can handle the external defs and local registry I needed.
Thanks!
我还发现会调用 Init() 方法,并且 _extensions 和 _mime 成员不会完全初始化,所以我将其更改为读取,最好的方法是从 MimeTypeCollection 的构造函数中删除调用 GetExtension:
I also found that the Init() method would be called and the _extensions and _mime members would not be completely initialized so I changed it to read, and the best way is, remove call GetExtension in constructor from MimeTypeCollection:
我想提醒您,不要在未根据文件的实际内容进行验证的情况下检索文件的 Mime/内容类型,因为这可能会给您的系统和用户带来严重的安全风险。
尽管存在此类的有效用例,但攻击者可能会攻击您的系统,或通过将可执行文件或脚本伪装成其他非可疑文件类型,将其用作向其他用户传播恶意文件的机制。
建议您在继续处理(或提供下载)之前认真考虑沙箱并对上传的文件执行深度内容检查。
I would just like to caution you against retrieving the Mime / content type of a file without validating it against the actual content of the file, as it could pose a serious security risk to your system and users.
Although there are valid use cases for something like this, attackers can potentially attack your system or use it as a mechanism to propagate malicious files to other users, by disguising executables or scripts as other, non-suspect file types.
It is advisable that you seriously consider sandboxing and performing deep content inspection on uploaded files before continuing to process it (or making it available for download).