在C#中,如何从byte []中知道文件类型?

时间:2009-10-31 16:25:43

标签: asp.net-mvc c#-3.0 bytearray content-type

我从上传的文件中填充了一个字节数组。但是,在代码的另一部分中,我需要知道从byte []上传的这种文件类型,这样我才能将正确的内容类型呈现给浏览器!

谢谢!

10 个答案:

答案 0 :(得分:20)

如前所述,MIME魔术是唯一的方法。许多平台提供最新且强大的MIME魔术文件和代码来有效地执行此操作。在没有任何第三方代码的.NET中执行此操作的唯一方法是使用urlmon.dll中的FindMimeFromData。方法如下:

public static int MimeSampleSize = 256;

public static string DefaultMimeType = "application/octet-stream";

[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
private extern static uint FindMimeFromData(
    uint pBC,
    [MarshalAs(UnmanagedType.LPStr)] string pwzUrl,
    [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
    uint cbSize,
    [MarshalAs(UnmanagedType.LPStr)] string pwzMimeProposed,
    uint dwMimeFlags,
    out uint ppwzMimeOut,
    uint dwReserverd
);

public static string GetMimeFromBytes(byte[] data) {
    try {
        uint mimeType;
        FindMimeFromData(0, null, data, (uint)MimeSampleSize, null, 0, out mimeType, 0);

        var mimePointer = new IntPtr(mimeType);
        var mime = Marshal.PtrToStringUni(mimePointer);
        Marshal.FreeCoTaskMem(mimePointer);

        return mime ?? DefaultMimeType;
    }
    catch {
        return DefaultMimeType;
    }
}

这使用Internet Explorer MIME检测器。这与IE用于发送MIME类型以及上载文件的代码相同。你可以看到list of MIME types supported by urlmon.dll。需要注意的一点是image/pjpegimage/x-png,这是非标准的。在我的代码中,我将其替换为image/jpegimage/png

答案 1 :(得分:9)

不确定,但也许您应该调查magic numbers

<强>更新 读到它,我认为它不是很可靠。

答案 2 :(得分:8)

您无法从字节流中知道它,但您可以在最初填充byte[]时存储MIME类型。

答案 3 :(得分:7)

简短回答:你不能

更长的答案:通常,程序使用文件扩展名来了解他们正在处理的文件类型。如果你没有那个扩展名,你只能猜测...例如,你可以查看前几个字节并检查你是否识别一个众所周知的标题(例如XML声明标记,或位图或JPEG标题) )。但最终总是猜测:如果没有一些元数据或有关内容的信息,一个字节数组就没有意义......

答案 4 :(得分:4)

如果你知道它是System.Drawing.Image,你可以这样做:

public static string GeMimeTypeFromImageByteArray(byte[] byteArray)
{
   using (MemoryStream stream = new MemoryStream(byteArray))
   using (Image image = Image.FromStream(stream))
   {
       return ImageCodecInfo.GetImageEncoders().First(codec => codec.FormatID == image.RawFormat.Guid).MimeType;
   }
}

答案 5 :(得分:2)

让我回想起当天我们,呃“有些人”曾经在早期免费图片托管网站上分享50MB rar文件,只需在.rar文件名中添加.gif扩展名即可。

显然,如果您面向公众并期望某种文件类型,并且您必须确定它是该文件类型,那么您不能只信任该扩展名。

另一方面,如果您的应用没有理由不信任上传的扩展名和/或MIME类型,那么只需在文件上传时获取,就像您从@rossfabircant和@RandolphPotter收到的答案一样。创建一个具有byte []的类型,以及原始扩展名或mimetype,并传递它。

如果您需要验证文件实际上是某个预期类型,如有效的.jpeg或.png,您可以尝试将该文件解释为这些类型,并查看它是否成功打开。 (System.Drawing.Imaging.ImageFormat)

如果您尝试仅从二进制内容对文件进行分类,并且它可能是整个世界中的任何格式,那实际上是一个棘手的开放式问题,并且没有100%可靠的方法来实现它。您可以针对它调用TrID,如果您能找到(并且负担得起),执法调查人员可能会使用类似的取证工具。

如果您不必这么做,请不要。

答案 6 :(得分:2)

如果知道文件名的扩展名,则可以使用System.Web.MimeMapping来解决问题:

MimeMapping.GetMimeMapping(fileDisplayNameWithExtension)

我在MVC Action中像这样使用它:

return File(fileDataByteArray, MimeMapping.GetMimeMapping(fileDisplayNameWithExtension), fileDisplayNameWithExtension);

答案 7 :(得分:1)

你不想这样做。上传文件时调用Path.GetExtension,并使用byte []传递扩展名。

答案 8 :(得分:0)

如果您希望支持有限数量的预期文件类型,可以使用幻数。

一种简单的检查方法是使用文本/十六进制编辑器打开示例文件,并研究前导字节以查看是否有可用于区分/丢弃文件与支持的集合的文件。

另一方面,如果您想要识别任意文件类型,是的,正如每个人已经说过的那样,很难。

答案 9 :(得分:0)

使用System.Drawing.Image'RawFormat.Guid'属性,您可以检测图像的MIME类型。

但我不确定如何找到其他文件类型。

http://www.java2s.com/Code/CSharp/Network/GetImageMimeType.htm

更新:您可以尝试查看此帖子

Using .NET, how can you find the mime type of a file based on the file signature not the extension