В C #, как я могу узнать тип файла из байта []? - PullRequest
27 голосов
/ 31 октября 2009

У меня есть байтовый массив, заполненный из загруженного файла. Но в другой части кода мне нужно знать этот тип файла, загруженный из байта [], чтобы я мог отобразить правильный тип содержимого в браузере!

Спасибо !!

Ответы [ 10 ]

20 голосов
/ 31 марта 2011

Как уже упоминалось, магия MIME - единственный способ сделать это. Многие платформы предоставляют современные и надежные магические файлы MIME и код для эффективной работы. Единственный способ сделать это в .NET без стороннего кода - использовать FindMimeFromData из urlmon.dll. Вот как:

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;
    }
}

Используется детектор MIME Internet Explorer. Это тот же код, который используется в IE для отправки типа MIME вместе с загруженными файлами. Вы можете увидеть список типов MIME, поддерживаемых urlmon.dll . Стоит обратить внимание на нестандартные image/pjpeg и image/x-png. В моем коде я заменяю их на image/jpeg и image/png.

9 голосов
/ 31 октября 2009

Не уверен, но, возможно, вам следует выяснить около магических чисел .

Обновление: Читая об этом, я не думаю, что это очень надежно.

8 голосов
/ 31 октября 2009

Вы не можете знать это из потока байтов, но вы можете сохранить тип MIME, когда вы первоначально заполняете byte[].

7 голосов
/ 31 октября 2009

Краткий ответ: вы не можете

Более длинный ответ: Обычно программы используют расширение файла, чтобы знать, с каким типом файла они имеют дело. Если у вас нет этого расширения, вы можете только догадываться ... например, вы можете посмотреть на первые несколько байтов и проверить, распознаете ли вы хорошо известный заголовок (например, тег объявления XML, или растровый или заголовок JPEG). ). Но это всегда будет предположение в конце: без каких-либо метаданных или информации о содержимом массив байтов просто бессмыслен ...

6 голосов
/ 08 декабря 2017

Если вы знаете, что это 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;
   }
}
2 голосов
/ 08 августа 2018

Если вы знаете расширение имени файла, возможно, System.Web.MimeMapping сделает свое дело:

MimeMapping.GetMimeMapping(fileDisplayNameWithExtension)

Я использовал его в MVC Action следующим образом:

return File(fileDataByteArray, MimeMapping.GetMimeMapping(fileDisplayNameWithExtension), fileDisplayNameWithExtension);
2 голосов
/ 04 ноября 2009

Напоминает мне о том, что когда-то мы, некоторые из нас, делились 50-мегабайтными rar-файлами на ранних бесплатных сайтах размещения изображений, просто добавив расширение .gif к имени файла .rar.

Очевидно, что если вы общедоступны и ожидаете определенного типа файлов, и вы должны быть уверены, что это тот тип файлов, то вы не можете просто доверять расширению.

С другой стороны, если у вашего приложения нет причин не доверять загруженному расширению и / или типу MIME, просто получите их при загрузке файла, как ответы, полученные от @rossfabircant и @RandolphPotter. создайте тип с байтом [], а также с исходным расширением или mimetype и передайте его.

Если вам нужно убедиться, что файл на самом деле относится к определенному ожидаемому типу, например, к действительному файлу .jpeg или .png, вы можете попытаться интерпретировать файл как эти типы и посмотреть, успешно ли он открывается. (System.Drawing.Imaging.ImageFormat)

Если вы пытаетесь классифицировать файл только из двоичного содержимого, и это может быть любой формат во всем мире, это действительно сложная, открытая проблема, и нет 100% надежного способа сделать это , Вы можете ссылаться на него TrID , и, вероятно, существуют аналогичные инструменты судебной экспертизы, используемые правоохранительными следователями, если вы можете их найти (и позволить себе).

Если вам не нужно делать это нелегко, не надо.

1 голос
/ 31 октября 2009

Вы не хотите делать это таким образом. Вызвать Path.GetExtension при загрузке файла и передать расширение с помощью байта [].

0 голосов
/ 25 февраля 2013

Используя свойство 'RawFormat.Guid' System.Drawing.Image, вы можете определить тип изображений MIME.

но я не уверен, как найти другие типы файлов.

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

ОБНОВЛЕНИЕ: Вы можете попробовать взглянуть на этот пост

Используя .NET, как вы можете найти MIME-тип файла на основе сигнатуры файла, а не расширения

0 голосов
/ 20 июня 2012

Если у вас есть ограниченное число ожидаемых типов файлов, которые вы хотите поддерживать, магические числа могут быть подходящим вариантом.

Простой способ проверить это - просто открыть файлы примеров в текстовом / шестнадцатеричном редакторе и изучить начальные байты, чтобы увидеть, есть ли там что-то, что вы можете использовать, чтобы отличить / отбросить файлы из поддерживаемого набора.

Если, с другой стороны, вы хотите распознать любой произвольный тип файла, да, как уже все говорили, жестко.

...