web-dev-qa-db-fra.com

En C #, comment puis-je connaître le type de fichier à partir d'un octet []?

J'ai un tableau d'octets rempli à partir d'un fichier téléchargé. Mais, dans une autre partie du code, j'ai besoin de connaître le type de fichier transféré à partir de l'octet [] pour pouvoir afficher le type de contenu correct dans le navigateur!

Merci!!

25
AndreMiranda

Pas sûr, mais peut-être devriez-vous vous renseigner sur les nombres magiques

Mise à jour: En lisant cela, je ne pense pas que ce soit très fiable cependant.

8
Carles Company

Comme mentionné, la magie MIME est le seul moyen de le faire. De nombreuses plates-formes fournissent des fichiers magiques et du code MIME robustes et à jour pour le faire efficacement. La seule façon de procéder dans .NET sans code tiers consiste à utiliser FindMimeFromData à partir de urlmon.dll. Voici comment:

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

Ceci utilise le détecteur Internet Explorer MIME. Il s'agit du même code utilisé par IE pour envoyer un type MIME avec les fichiers téléchargés. Vous pouvez voir la liste des types MIME supportés par urlmon.dll . Une chose à surveiller est image/pjpeg et image/x-png qui ne sont pas standard. Dans mon code, je les remplace par image/jpeg et image/png.

19
mroach

Vous ne pouvez pas le savoir à partir du flux d'octets, mais vous pouvez stocker le type MIME lorsque vous remplissez initialement le byte[].

8
user114600

Réponse courte: vous ne pouvez pas

Réponse plus longue: en général, les programmes utilisent l'extension de fichier pour savoir à quel type de fichier ils font face. Si vous n'avez pas cette extension, vous ne pouvez que deviner ... par exemple, vous pouvez regarder les premiers octets et vérifier si vous reconnaissez un en-tête connu (balise de déclaration XML par exemple, ou en-tête bitmap ou JPEG ). Mais ce sera toujours une hypothèse à la fin: sans quelques métadonnées ou informations sur le contenu, un tableau d'octets n'a pas de sens ...

7
Thomas Levesque

Si vous savez que c'est un System.Drawing.Image , vous pouvez faire:

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

Cela me rappelle que, à l'époque, "certaines personnes" partageaient déjà 50 Mo de fichiers rar sur les premiers sites d'hébergement d'images gratuites, en ajoutant simplement l'extension .gif au nom de fichier .rar. 

Il est clair que si vous faites face à un public et attendez un certain type de fichier et que vous devez vous assurer qu'il s'agit bien de ce type de fichier, vous ne pouvez pas simplement faire confiance à l'extension. 

D'autre part, si votre application n'a aucune raison de se méfier de l'extension et/ou du type MIME téléchargés, récupérez-les simplement lorsque le fichier est chargé, comme les réponses que vous avez reçues de @rossfabircant et @RandolphPotter. créez un type qui a l'octet [], ainsi que l'extension ou le type MIME d'origine, et transmettez-le.

Si vous devez vérifier que le fichier correspond bien à un certain type attendu, tel qu'un fichier .jpeg ou .png valide, vous pouvez essayer d'interpréter le fichier comme étant de ce type et voir s'il s'ouvre correctement. (System.Drawing.Imaging.ImageFormat)

Si vous essayez de classer le fichier uniquement à partir du contenu binaire, et qu'il s'agisse d'un format quelconque dans le monde entier, il s'agit d'un problème difficile à résoudre et il n'existe pas de moyen fiable à 100% de le faire. Vous pouvez invoquer TrID contre cela, et il existe probablement des outils médico-légaux similaires utilisés par les enquêteurs de l’application de la loi si vous pouvez les trouver (et vous en procurer).

Si vous n'êtes pas obligé de le faire à la dure, ne le faites pas.

2
DanO

Vous ne voulez pas le faire de cette façon. Appelez Path.GetExtension lors du téléchargement du fichier et transmettez l'extension avec l'octet [].

1
RossFabricant

À l'aide de la propriété 'RawFormat.Guid' de System.Drawing.Image, vous pouvez détecter le type MIME des images.

mais je ne suis pas sûr de savoir comment trouver d'autres types de fichiers.

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

UPDATE: vous pouvez essayer de jeter un coup d'oeil sur ce post

À l'aide de .NET, comment trouver le type mime d'un fichier basé sur la signature du fichier et non sur l'extension

0

Si vous souhaitez prendre en charge un nombre limité de types de fichiers attendus, vous pouvez utiliser des nombres magiques.

Un moyen simple de vérifier consiste simplement à ouvrir des exemples de fichiers avec un éditeur texte/hexadécimal et à étudier les octets de tête pour voir s’il ya quelque chose que vous pouvez utiliser pour différencier/ignorer les fichiers du jeu pris en charge.

Si, par contre, vous cherchez à reconnaître tout type de fichier arbitraire, oui, comme tout le monde l’a déjà dit, difficile.

0
Oskuro

Si vous connaissez l'extension du nom du fichier, System.Web.MimeMapping fera l'affaire:

MimeMapping.GetMimeMapping(fileDisplayNameWithExtension)

Je l'ai utilisé dans MVC Action comme ceci:

return File(fileDataByteArray, MimeMapping.GetMimeMapping(fileDisplayNameWithExtension), fileDisplayNameWithExtension);
0
Yasser Sobhdel