如何从文件扩展名中获得MIME类型?


当前回答

由文件扩展名计算的mime类型不一定总是正确的。

让我们说,我可以保存一个文件的。png扩展名,但文件格式,我可以设置为“ImageFormat.jpeg”。

所以在这种情况下,你要计算的文件会给出不同的结果…这可能会导致文件比原始文件大。

如果你正在处理图像,那么你可以使用imagecodecInfo和ImageFormat。

其他回答

ASP。NET或其他

在ASP中,选项发生了一些变化。NET Core,在这里(学分):

新FileExtensionContentTypeProvider()。TryGetContentType(文件名,输出内容类型);(仅vNext) 从未测试过,但看起来您可以通过公开的Mappings属性正式展开mime类型列表。 使用MimeTypes NuGet包 从.NET Framework的引用源中复制mimemaps文件

对于。net Framework >= 4.5:

使用System.Web.MimeMapping.GetMimeMapping方法,这是.NET Framework 4.5中BCL的一部分:

string mimeType = MimeMapping.GetMimeMapping(fileName);

如果你需要添加自定义映射,你可以使用反射来向BCL MimeMapping类添加映射,它使用一个自定义字典来公开这个方法,所以你应该调用下面的方法来添加映射(从未测试过,但应该问题。工作)。

无论如何,当使用反射来添加MIME类型时,要注意,由于您正在访问私有字段,因此它的名称可能会更改甚至完全被删除,因此您应该格外谨慎,添加双重检查并为每一步提供故障安全操作。

MimeMapping._mappingDictionary.AddMapping(string fileExtension, string mimeType)

如果你不想增加额外的依赖关系,并且仍然想要版本独立的请求,你可以把这个关于如何在不同的。net版本中获得MIME-Type的答案与这个关于多个。net框架版本的条件构建的答案混合在一起。

我做的第一件事是编辑我的项目文件。在最后一个构建定义之后,我添加了第二个答案中所述的属性组:

<PropertyGroup>
    <DefineConstants Condition=" !$(DefineConstants.Contains(';NET')) ">$(DefineConstants);$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</DefineConstants>
    <DefineConstants Condition=" $(DefineConstants.Contains(';NET')) ">$(DefineConstants.Remove($(DefineConstants.LastIndexOf(";NET"))));$(TargetFrameworkVersion.Replace("v", "NET").Replace(".", ""))</DefineConstants>
</PropertyGroup>

现在我为MimeExtensionHelper提供了一个与第一个答案不同的实现,并为所有来自。net 4.5或更高版本的客户端提供了一个额外的实现,只需调用System.Web.MimeMapping.GetMimeMapping:

#if (NET10 || NET11 || NET20 || NET30 || NET35)
public static class MimeExtensionHelper
{
    static object locker = new object();
    static MethodInfo getMimeMappingMethodInfo;

    static MimeExtensionHelper()
    {
        Type mimeMappingType = Assembly.GetAssembly(typeof(HttpRuntime)).GetType("System.Web.MimeMapping");

        if (mimeMappingType == null)
            throw new SystemException("Couldnt find MimeMapping type");

        ConstructorInfo constructorInfo = mimeMappingType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);

        if (constructorInfo == null)
            throw new SystemException("Couldnt find default constructor for MimeMapping");

        mimeMapping = constructorInfo.Invoke(null);

        if (mimeMapping == null)
            throw new SystemException("Couldnt find MimeMapping");

        getMimeMappingMethodInfo = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);

        if (getMimeMappingMethodInfo == null)
            throw new SystemException("Couldnt find GetMimeMapping method");

        if (getMimeMappingMethodInfo.ReturnType != typeof(string))
            throw new SystemException("GetMimeMapping method has invalid return type");

        if (getMimeMappingMethodInfo.GetParameters().Length != 1 && getMimeMappingMethodInfo.GetParameters()[0].ParameterType != typeof(string))
            throw new SystemException("GetMimeMapping method has invalid parameters");
    }

    public static string GetMimeType(string fileName)
    {
        lock (locker)
        {
            return (string)getMimeMappingMethodInfo.Invoke(null, new object[] { fileName });
        }
    }
}
#elif NET40
public static class MimeExtensionHelper
{
    static object locker = new object();
    static MethodInfo getMimeMappingMethodInfo;

    static MimeExtensionHelper()
    {
        Type mimeMappingType = Assembly.GetAssembly(typeof(HttpRuntime)).GetType("System.Web.MimeMapping");

        if (mimeMappingType == null)
            throw new SystemException("Couldnt find MimeMapping type");           

        getMimeMappingMethodInfo = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);

        if (getMimeMappingMethodInfo == null)
            throw new SystemException("Couldnt find GetMimeMapping method");

        if (getMimeMappingMethodInfo.ReturnType != typeof(string))
            throw new SystemException("GetMimeMapping method has invalid return type");

        if (getMimeMappingMethodInfo.GetParameters().Length != 1 && getMimeMappingMethodInfo.GetParameters()[0].ParameterType != typeof(string))
            throw new SystemException("GetMimeMapping method has invalid parameters");
    }

    public static string GetMimeType(string fileName)
    {
        lock (locker)
        {
            return (string)getMimeMappingMethodInfo.Invoke(null, new object[] { fileName });
        }
    }
}
#else // .NET 4.5 or later
public static class MimeExtensionHelper
{
    public static string GetMimeType(string fileName)
    {
        return MimeMapping.GetMimeMapping(fileName);
    }
}
#endif

同样在。net 4.5之前的版本中,静态MimeMapping类拥有一个名为_mappingDictionary的静态实例(类型为MimeMapping. mimemappingdictionarybase),您可以从反射请求该实例,以便添加可能还不支持的新的MIME-Types。

您可以在注册表中找到这些信息。例如,.pdf文件的MIME类型可以在键HKEY_CLASSES_ROOT\.pdf中找到,在值"Content type "中:

string mimeType = Registry.GetValue(@"HKEY_CLASSES_ROOT\.pdf", "Content Type", null) as string;

我对这些mimetypes的理解,使用apache列表,下面的脚本将为您提供一个包含所有mimetypes的字典。

var mimeTypeListUrl = "http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types";
var webClient = new WebClient();
var rawData = webClient.DownloadString(mimeTypeListUrl).Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries);

var extensionToMimeType = new Dictionary<string, string>();
var mimeTypeToExtension = new Dictionary<string, string[]>();

foreach (var row in rawData)
{
    if (row.StartsWith("#")) continue;

    var rowData = row.Split(new[] { "\t" }, StringSplitOptions.RemoveEmptyEntries);
    if (rowData.Length != 2) continue;

    var extensions = rowData[1].Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
    if (!mimeTypeToExtension.ContainsKey(rowData[0]))
    {
        mimeTypeToExtension.Add(rowData[0], extensions);
    }

    foreach (var extension in extensions)
    {
        if (!extensionToMimeType.ContainsKey(extension))
        {
            extensionToMimeType.Add(extension, rowData[0]);
        }
    }

}

由文件扩展名计算的mime类型不一定总是正确的。

让我们说,我可以保存一个文件的。png扩展名,但文件格式,我可以设置为“ImageFormat.jpeg”。

所以在这种情况下,你要计算的文件会给出不同的结果…这可能会导致文件比原始文件大。

如果你正在处理图像,那么你可以使用imagecodecInfo和ImageFormat。