В C#, как я могу узнать тип файла из байта[]?

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

спасибо!!

10 ответов


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

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


как уже упоминалось, мимическая магия-единственный способ сделать это. Многие платформы предоставляют современные и надежные магические файлы и код MIME, чтобы сделать это эффективно. Единственный способ сделать это .Чистая без 3 код партии использовать 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.


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


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

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


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

напоминает мне о том дне, когда мы, э-э ... "некоторые люди" использовали для обмена файлами 50MB rar на ранних бесплатных сайтах хостинга изображений, просто добавив .расширение gif для .rar filename.

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

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

Если вам нужно проверить, что файл на самом деле является определенным ожидаемым типом, таким как valid .JPEG или .png вы можете попытаться интерпретировать файл как эти типы и посмотреть, успешно ли он открывается. (Система.Рисунок.Изображений.ImageFormat)

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

Если вам не нужно делать это тяжелым способом, не делайте.


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


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

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

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


использование системы.Рисунок.Изображение ' RawFormat.Свойство Guid вы можете обнаружить тип MIME изображений.

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

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

обновление: вы можете попробовать взглянуть на этот пост

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


Если вы знаете расширение имени файла, может быть система.Сеть.MimeMapping сделает трюк:

MimeMapping.GetMimeMapping(fileDisplayNameWithExtension)

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

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