2010-05-13 16 views
6

tengo un flujo de trabajo donde el usuario puede cargar cualquier archivo y luego ese archivo se leerá.cómo identificar la extensión/tipo del archivo usando C#?

Ahora mi pregunta es si el usuario tiene el archivo de imagen xyz.jpg y lo renombró a xyz solamente (extensión eliminada) en esto todavía podemos obtener el tipo/extensión del archivo utilizando/leyendo archivos de datos/metadatos.

Gracias a todos

+2

Que no se carguen archivos sin extensión! :) – JohnIdol

+1

posible duplicado de [Usando .NET, ¿cómo puede encontrar el tipo de mimo de un archivo basado en la firma del archivo, no la extensión. ] (Http://stackoverflow.com/questions/58510/using-net-how-can-you-find-the-mime-type-of-a-file-based-on-the-file-signature) –

+0

I de acuerdo: los archivos sin extensiones son de valor cuestionable para un usuario, ¿qué los hace pensar que podrían ser de más valor para usted? Esto no es un comportamiento esperado y no debe generar una complejidad adicional de su parte. –

Respuesta

11

Ver PInvoke.net para más detalles

[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); 

Ejemplo de uso:

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")); 

Otro ejemplo:

/// <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

Sí, probablemente para muchos tipos de archivos que esto es posible, pero requeriría el análisis del contenido binario del archivo en una base de caso por caso.

3

Usted puede utilizar la función no administrado FindMimeFromData en 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 
); 

Ver here para un uso de ejemplo.

+0

+1 - muy bueno, no sabía de eso. ¿Cree que el ContentType de HttpPostedFile se establece consultando esto? También - encontrado otro q con un ejemplo de código: http://stackoverflow.com/questions/58510/using-net-how-can-you-find-the-mime-type-of-a-file-based-on- el archivo de firmas –

+0

@Andras el tipo de contenido del archivo enviado se fija arbitrariamente por el cartel (código, navegador, flash, etc) y no debe ser dependido menos que tenga un ambiente muy controlado. –

+0

Me di cuenta de eso y lo recuperé rápidamente. ;-) y también estuvo de acuerdo en otro punto. –

0

¿Hay formatos de archivo específicos que necesita para detectar? Hace la tarea mucho más fácil si puede limitarla a unos pocos formatos que pueden identificarse por el contenido del archivo.

Si necesita detectar una amplia gama de tipos de archivos, existen kits de herramientas de terceros que puede utilizar, pero te advierten de que tienden a ser muy caro. Los dos con los que estoy familiarizado son Stellent's (now Oracle's) Outside In y Autonomy Keyview. Ambos proporcionan kits de herramientas de programador.

0

Si sólo tiene que ver si el archivo subido es una imagen, simplemente analizar en consecuencia

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