esiste una funzione di sistema FindMimeFromData che è capace di trovare 26 tipi di file sniffando dai prima 256 bytes, con il compromesso di utilizzare un po' di unmanaged code:
http://msdn.microsoft.com/en-us/library/ms775147%28VS.85%29.aspx#Known_MimeTypes
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
);
// leggi nel buffer i primi 256 byte del file
System.UInt32 mimetype;
FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
System.IntPtr mimeTypePtr = new IntPtr(mimetype);
string mime = Marshal.PtrToStringUni(mimeTypePtr);
Marshal.FreeCoTaskMem(mimeTypePtr);
altrimenti, per gli zip dalla wiki ho letto "when a .ZIP file is viewed in a text editor the first two bytes of the file are usually "PK"" http://en.wikipedia.org/wiki/Zip_(file_format) sezione struttura, subito dopo c'è la tabella dell'header dove dice che i primi 4 bytes dovrebbero essere 0x04034b50. Io aprendo qualche zip di fatto mi ritrovo con "PK" all'inizio, sicuramente il metodo FindMimeFromData sarà più accurato ma non ne conosco il codice.
comunque un possibile codice (preso da http://stackoverflow.com/questions/11996299/c-net-identify-zip-file) basandosi sull'header della wiki pyò essere così:
abstract class Expander
{
private const int ZIP_LEAD_BYTES = 0x04034b50;
private const ushort GZIP_LEAD_BYTES = 0x8b1f;
public abstract MemoryStream Expand(Stream stream);
internal static bool IsPkZipCompressedData(byte[] data)
{
Debug.Assert(data != null && data.Length >= 4);
// if the first 4 bytes of the array are the ZIP signature then it is compressed data
return (BitConverter.ToInt32(data, 0) == ZIP_LEAD_BYTES);
}
internal static bool IsGZipCompressedData(byte[] data)
{
Debug.Assert(data != null && data.Length >= 2);
// if the first 2 bytes of the array are theG ZIP signature then it is compressed data;
return (BitConverter.ToUInt16(data, 0) == GZIP_LEAD_BYTES);
}
public static bool IsCompressedData(byte[] data)
{
return IsPkZipCompressedData(data) || IsGZipCompressedData(data);
}
public static Expander GetExpander(Stream stream)
{
Debug.Assert(stream != null);
Debug.Assert(stream.CanSeek);
stream.Seek(0, 0);
try
{
byte[] bytes = new byte[4];
stream.Read(bytes, 0, 4);
if (IsGZipCompressedData(bytes))
return new GZipExpander();
if (IsPkZipCompressedData(bytes))
return new ZipExpander();
return new NullExpander();
}
finally
{
stream.Seek(0, 0); // set the stream back to the begining
}
}
}
poi è anche vero che dalla stessa wiki si legge: "Tools that correctly read .ZIP archives must scan for the end of central directory record signature, and then, as appropriate, the other, indicated, central directory records." quindi spostarsi in fondo al file e controllare se esiste questo central directory signature, quindi diciamo per l'header non è un metodo completamente affidabile, ma molto probabilmente ti può bastare come basta a windows internet explorer (dato che controlla solo i primi 256 byte).
altre info sugli zip: http://petlibrary.tripod.com/ZIP.HTM
ciao,
Michael Denny
Software Developer & Architect
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
Twitter: @dennymic