在ASP.NET C#中如何获取请求的文件的MIME类型?

7
我希望可以根据MIME类型不同来处理请求。例如,我有PDF文件、图像和其他媒体文件,我想根据它们各自的MIME类型禁止访问。你有什么好的建议吗?感谢您的帮助。
另外,我应该注意到,访问Windows注册表对于我的应用程序不是一种选择。

这与上传这些文件或下载的限制有关吗? - REA_ANDREW
这与下载和/或URL重写有关。 - mkelley33
如果您正在使用ASP.NET Core,请参见https://dev59.com/tlsX5IYBdhLWcg3wLc-J#35880687。 - Theophilus
5个回答

11

.NET 的 MIME 类型映射存储在 System.Web.MimeMapping 类中,该类提供 GetMimeMapping 方法。

在 .NET 4.5 之前,这个类被标记为 internal,因此不可用于你的代码。在这种情况下,你最好偷取这个列表,可以使用 Reflector 并反编译静态构造函数 (cctor)。

如果采用这种方法,你可以更好地创建一个支持的扩展名及其 MIME 类型列表,并将其存储在字典中。(MimeMapping 中的列表有点冗长)


这正是我采取的路线。我肯定错过了一些扩展,但它们很可能是最好作为出现以满足“高效/工作软件”要求的边缘情况来处理的。谢谢你的建议!我从未听说过MimeMappings。非常酷! - mkelley33
3
从4.5版本开始,这个类已经公开发布了!使用方便的GetMimeMapping(string fileName)方法。- http://msdn.microsoft.com/en-us/library/system.web.mimemapping.getmimemapping.aspx - Snixtor

9

几个月前,我遇到了类似的问题,并通过使用 System.Web.MimeMapping 中提到的这个简单的包装类来解决它(由 Richard Szalay 提供):

/// <summary>
/// This class allows access to the internal MimeMapping-Class in System.Web
/// </summary>
class MimeMappingWrapper
{
    static MethodInfo getMimeMappingMethod;

    static MimeMappingWrapper() {
        // dirty trick - Assembly.LoadWIthPartialName has been deprecated
        Assembly ass = Assembly.LoadWithPartialName("System.Web");
        Type t = ass.GetType("System.Web.MimeMapping");

        getMimeMappingMethod = t.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);
    }

    /// <summary>
    /// Returns a MIME type depending on the passed files extension
    /// </summary>
    /// <param name="fileName">File to get a MIME type for</param>
    /// <returns>MIME type according to the files extension</returns>
    public static string GetMimeMapping(string fileName) {
        return (string)getMimeMappingMethod.Invoke(null, new[] { fileName });
    }
}

1
避免使用脏代码的方法是否有问题,通过引用公共类型 Assembly.GetAssembly(typeof(System.Web.HttpApplication))。只要方法和引用的类型不改变或消失,那就可以这样做...? - Nelson Rothermel
6
我喜欢你给汇编起的变量名。 - Ivan G.

8

为什么反射突然找不到任何东西?交叉发布

好消息是,MimeMapping类及其GetMimeMapping方法在.NET 4.5中似乎已公开。

但是,这意味着上面的答案中给出的代码将会失效,因为它只在NonPublic方法中搜索GetMimeMapping

为确保与.NET 4.5兼容(但保留.NET 4.0及更早版本的功能),请更改...

getMimeMappingMethod = t.GetMethod("GetMimeMapping", 
    BindingFlags.Static | BindingFlags.NonPublic);

…to:

getMimeMappingMethod = t.GetMethod("GetMimeMapping",
    BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);

不错的内容..虽然我不太明白。我仍然在使用.NET 4,但框架似乎表现得像你描述的那样(就像在.NET 4.5中)..非常奇怪。 - mare
1
@mare 你可能已经安装了.NET 4.5 -- 它是一种就地升级,因此在运行时程序集将具有新代码,但在编译时,VS会限制您只能使用.NET 4.0可用的代码。 - JT.

1

这个信息保存在注册表中,在 HKEY_CLASSES_ROOT\<file_extension>\Content Type 中。

using(var key = Registry.ClassesRoot.OpenSubKey(".htm"))
{
    string mimeType = key.GetValue("Content Type") as string;
}

1
谢谢您的建议,但是我手头的技术要求规定不能访问注册表。 - mkelley33

0
如果我正确理解您的问题,您正在提供静态文件并希望能够在处理静态文件请求时进行处理,以便根据MIME类型决定用户是否有权访问该文件。
如果您将所有文件请求映射到自定义IHttpHandler(请参阅web.config文件的处理程序部分),则应该能够实现此目的。
在ProcessRequest(或BeginProcessRequest,如果您实现了异步处理程序)中,您可以调用HttpContext.Current.Server.MapPath(“〜”+ HttpContext.Current.Request.Path)(可能有更好的方法)来获取当前请求的静态文件。
然后,您可以分析该文件的扩展名以做出决策。
不确定这是否符合您的要求,但希望能有所帮助。

这非常接近我想要的,但我希望有一种更自动化的方法来完成它,而不是分析扩展名。更像Request.MIMEType这样的东西。感谢您的意见! - mkelley33

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