Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Urlmon.dll中FindMimeFromData方法的替代方法具有更多MIME类型的方法_C#_Mime Types - Fatal编程技术网

C# Urlmon.dll中FindMimeFromData方法的替代方法具有更多MIME类型的方法

C# Urlmon.dll中FindMimeFromData方法的替代方法具有更多MIME类型的方法,c#,mime-types,C#,Mime Types,通过Windows DLLUrlmon.DLL访问的方法能够确定存储在内存中的给定数据的MIME类型,考虑到存储这些数据的字节数组的前256个字节 然而,在阅读了它的文档之后,我找到了这个方法能够识别的MIME类型。看见如您所见,此方法仅限于26种MIME类型 因此,我想知道是否有人可以给我指出另一个具有更多MIME类型的方法,或者另一个方法/类,如果我能够包含我认为合适的MIME类型。有多种可能的解决方案,至少可以让您思考一下 似乎唯一真正的方法是以二进制形式读取它,然后进行比较,不管MIME

通过Windows DLL
Urlmon.DLL
访问的方法能够确定存储在内存中的给定数据的MIME类型,考虑到存储这些数据的字节数组的前256个字节

然而,在阅读了它的文档之后,我找到了这个方法能够识别的MIME类型。看见如您所见,此方法仅限于26种MIME类型


因此,我想知道是否有人可以给我指出另一个具有更多MIME类型的方法,或者另一个方法/类,如果我能够包含我认为合适的MIME类型。

有多种可能的解决方案,至少可以让您思考一下


似乎唯一真正的方法是以二进制形式读取它,然后进行比较,不管MIME类型是以某种方式声明为硬编码的,还是依赖计算机自己的可用MIME类型/注册表。

更新:@GetoX已将此代码打包到.net core的NuGet包中!看下面,干杯

所以我想知道是否有人能给我指出另一种方法 更多的MIME类型,或者我想要的另一个方法/类 能够包含我认为合适的MIME类型

我使用Winista和URLMon的混合来检测上传文件的真实格式

Winista MIME检测

假设有人使用jpg扩展名重命名exe,您仍然可以使用二进制分析确定“真实”文件格式。它不检测swf或flv,但几乎可以检测所有其他已知格式+您可以获得一个十六进制编辑器并添加更多它可以检测到的文件

文件魔法

Winista使用XML文件“MIME type.XML”检测真正的MIME类型,该文件包含有关文件类型和用于标识内容类型的签名的信息。例如:

<!--
 !   Audio primary type
 ! -->

<mime-type name="audio/basic"
           description="uLaw/AU Audio File">
    <ext>au</ext><ext>snd</ext>
    <magic offset="0" type="byte" value="2e736e64000000"/>
</mime-type>

<mime-type name="audio/midi"
           description="Musical Instrument Digital Interface MIDI-sequention Sound">
    <ext>mid</ext><ext>midi</ext><ext>kar</ext>
    <magic offset="0" value="MThd"/>
</mime-type>

<mime-type name="audio/mpeg"
           description="MPEG Audio Stream, Layer III">
    <ext>mp3</ext><ext>mp2</ext><ext>mpga</ext>
    <magic offset="0" value="ID3"/>
</mime-type>
在Winista方法内部,我在这里使用URLMon:

   public MimeType GetMimeTypeFromFile(string filePath)
    {
        sbyte[] fileData = null;
        using (FileStream srcFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] data = new byte[srcFile.Length];
            srcFile.Read(data, 0, (Int32)srcFile.Length);
            fileData = Winista.Mime.SupportUtil.ToSByteArray(data);
        }

        MimeType oMimeType = GetMimeType(fileData);
        if (oMimeType != null) return oMimeType;

        //We haven't found the file using Magic (eg a text/plain file)
        //so instead use URLMon to try and get the files format
        Winista.MimeDetect.URLMONMimeDetect.urlmonMimeDetect urlmonMimeDetect = new Winista.MimeDetect.URLMONMimeDetect.urlmonMimeDetect();
        string urlmonMimeType = urlmonMimeDetect.GetMimeFromFile(filePath);
        if (!string.IsNullOrEmpty(urlmonMimeType))
        {
            foreach (MimeType mimeType in types)
            {
                if (mimeType.Name == urlmonMimeType)
                {
                    return mimeType;
                }
            }
        }

        return oMimeType;
    }
。他们发现了一些“开源Nutch crawler系统中的mime阅读器实用程序类”,并在2000年初进行了C#重写

我已经使用Winista主持了我的MimeDetect项目,URLMon将返回此处(请使用十六进制编辑器提供新的文件类型):

您也可以使用Registry方法或Paul Zahra在linked to中提到的方法,但Winista是最好的IMHO

享受了解您系统上的文件与它们声称的是什么而不是什么的乐趣


更新:

对于桌面应用程序,您可能会发现WindowsAPICodePack工作得更好:

using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

private static string GetFilePropertyItemTypeTextValueFromShellFile(string filePathWithExtension)
{
   var shellFile = ShellFile.FromFilePath(filePathWithExtension);
   var prop = shellFile.Properties.GetProperty(PItemTypeTextCanonical);
   return prop.FormatForDisplay(PropertyDescriptionFormatOptions.None);
}

经过几个小时的寻找弹性解决方案。我采用了@JeremyThompson解决方案,将其改编为frameworks.NETCore/.NET4.5,并将其应用于

刚找到。它实际上是一个很好的替代方案,在面向Linux的应用程序上也运行良好

上下文
Urlmon.dll
不适用于Linux,因此不适用于多平台应用程序。 我在微软文档中找到了。它引用了一个非常好的文件类型参考(在我写这篇文章时是518)

再多挖掘一点,我发现了一个相当不错的项目:nuget。它还具有很强的可扩展性,例如,您可以从filesignatures.net获取所需的所有类型,并创建自己的类型模型

用法 您可以检查任何已定义的类型

var格式=inspector.DetermineFileFormat(流);
if(格式为Pdf){
//只匹配Pdf
}
if(格式为OfficeOpenXml){
//匹配Word、Excel、Powerpoint
}
if(格式为图像){
//匹配任何图像格式
}
或者根据匹配的文件类型使用它带来的一些元数据

var fileFormat = _fileFormatInspector.DetermineFileFormat(stream);
var mime = fileFormat?.MediaType;
扩展性 您可以定义从
FileFormat
继承的任意数量的类型,并配置
FileFormatLocator
在需要时加载它们

var assembly=typeof(CustomFileFormat).GetTypeInfo().assembly;
//仅包含CustomFileFormat的程序集中定义的格式
var customFormats=FileFormatLocator.GetFormats(程序集);
//程序集中定义的格式和所有默认值
var allFormats=FileFormatLocator.GetFormats(assembly,true);

中的更多详细信息我不确定这是否是您想要的,但您可以从IIS获得主要MIME类型的列表。但是FindMimeFromData方法硬编码为26种MIME类型,我无法修改它以接受更多MIME类型。在这种情况下,您可能会找到另一种方法来完成任务。如果您能找到要读取的数据类型的“扩展名”,您可能有更多的机会确定mime类型,如果您只想通过读取二进制数据来了解mime类型,那么据我所知,您必须限制为FindMimeFromData方法。这是一个安全敏感问题(因此固定26硬编码检测)。事实上,根据操作系统版本和各种配置,可以/可以禁用此MIME检测(Microsoft在过去遇到过实际问题)。我认为你不会在Windows API中找到替代方案。你可以重写你自己的。这个链接可以给你一些启示:@SimonMourier+1这就是为什么微软会限制自己的MIME检测。我也不相信我会找到另一个Windows API替代方案,我想唯一的办法就是自己编写。但我会等待,看看是否有人知道微软API的替代品。+1感谢链接,如果我决定构建自己的FindMineFromData替代品,贴在上面的答案应该会很有用。谢谢Jeremy。我喜欢你的答案,但是,当涉及到依赖Urlmon.dll中的FindMimeFromData方法时,我会非常小心,因为我已经读到(如果我没记错的话),它可能返回错误的MIME类型,如果在Windows注册表的某个给定位置没有定义适当的MIME类型,而且这些值也可能被篡改,这在将其发送给最终用户时会产生问题。考虑到这一点,我认为
   //init
   var mimeTypes = new MimeTypes();

   //usage by filepath
   var mimeType1 = mimeTypes.GetMimeTypeFromFile(filePath);

   //usage by bytearray
   var mimeType2 = mimeTypes.GetMimeTypeFromFile(bytes);
var fileFormat = _fileFormatInspector.DetermineFileFormat(stream);
var mime = fileFormat?.MediaType;