Как определить расширение/тип файла с помощью С#?

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

Теперь мой вопрос: если у пользователя есть файл изображения xyz.jpg, и он переименовал его только в xyz (расширение было удалено), мы можем получить тип/расширение файла с использованием/чтения файлов данных/метаданных.

Спасибо всем

Ответ 1

Подробнее см. PInvoke.net

   [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
    static extern int FindMimeFromData(IntPtr pBC,
          [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
         [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I1, SizeParamIndex=3)] 
        byte[] pBuffer,
          int cbSize,
             [MarshalAs(UnmanagedType.LPWStr)]  string pwzMimeProposed,
          int dwMimeFlags,
          out IntPtr ppwzMimeOut,
          int dwReserved);

Использование образца:

  public string MimeTypeFrom(byte[] dataBytes, string mimeProposed) {
   if (dataBytes == null)
     throw new ArgumentNullException("dataBytes");
   string mimeRet = String.Empty;
   IntPtr suggestPtr = IntPtr.Zero, filePtr = IntPtr.Zero, outPtr = IntPtr.Zero;
   if (mimeProposed != null && mimeProposed.Length > 0) {
     //suggestPtr = Marshal.StringToCoTaskMemUni(mimeProposed); // for your experiments ;-)
     mimeRet = mimeProposed;
   }
   int ret = FindMimeFromData(IntPtr.Zero, null, dataBytes, dataBytes.Length, mimeProposed, 0, out outPtr, 0);
   if (ret == 0 && outPtr != IntPtr.Zero) {
    //todo: this leaks memory outPtr must be freed
     return Marshal.PtrToStringUni(outPtr);
   }
   return mimeRet;
}

// call it this way:
Trace.Write("MimeType is " + MimeTypeFrom(Encoding.ASCII.GetBytes("%PDF-"), "text/plain"));

Другой пример:

/// <summary>
/// Ensures that file exists and retrieves the content type 
/// </summary>
/// <param name="file"></param>
/// <returns>Returns for instance "images/jpeg" </returns>
public static string getMimeFromFile(string file)
{
    IntPtr mimeout;
    if (!System.IO.File.Exists(file))
    throw new FileNotFoundException(file + " not found");

    int MaxContent = (int)new FileInfo(file).Length;
    if (MaxContent > 4096) MaxContent = 4096;
    FileStream fs = File.OpenRead(file);


    byte[] buf = new byte[MaxContent];        
    fs.Read(buf, 0, MaxContent);
    fs.Close();
    int result = FindMimeFromData(IntPtr.Zero, file, buf, MaxContent, null, 0, out mimeout, 0);

    if (result != 0)
    throw Marshal.GetExceptionForHR(result);
    string mime = Marshal.PtrToStringUni(mimeout);
    Marshal.FreeCoTaskMem(mimeout);
    return mime;
}

Ответ 2

Вы можете использовать неуправляемую функцию FindMimeFromData в urlmon.dll.

using System.Runtime.InteropServices;

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

См. здесь для примера использования.

Ответ 3

Да, возможно, для многих типов файлов это возможно, но для каждого случая потребуется разбор двоичного содержимого файла.

Ответ 4

Существуют ли определенные форматы файлов, которые необходимо обнаружить? Это облегчает задачу, если вы можете сузить ее до нескольких форматов, которые могут быть идентифицированы содержимым файла.

Если вам нужно обнаружить широкий диапазон типов файлов, есть сторонние инструментальные средства, которые вы можете использовать, но я предупрежу вас, что они, как правило, очень дороги. Мне знакомы два: Stellent (теперь Oracle) Outside In и Автономия. Оба предоставляют программные средства для программистов.

Ответ 5

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

try
{
Image image = Bitmap.FromStream(fileData);
}
catch(Exception e)
{
    // this isn't an image.
}