wake-up-neo.net

Wie kann ich in C # den Dateityp aus einem Byte [] ermitteln?

Ich habe ein Byte-Array aus einer hochgeladenen Datei gefüllt. Aber in einem anderen Teil des Codes muss ich diesen Dateityp kennen, der aus dem Byte [] hochgeladen wurde, damit ich den richtigen Inhaltstyp für den Browser rendern kann!

Vielen Dank!!

25
AndreMiranda

Nicht sicher, aber vielleicht sollten Sie nach magischen Zahlen suchen. 

Update: Wenn ich darüber lese, finde ich es nicht sehr zuverlässig.

8
Carles Company

Wie erwähnt, ist MIME-Magie die einzige Möglichkeit, dies zu tun. Viele Plattformen bieten aktuelle und robuste MIME-Magic-Dateien und Code, um dies effizient zu erledigen. Die einzige Möglichkeit, dies in .NET ohne Code von Drittanbietern zu tun, besteht in der Verwendung von FindMimeFromData aus urlmon.dll. Hier ist wie:

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

Hierbei wird der Internet Explorer-MIME-Detektor verwendet. Dies ist derselbe Code, der von IE verwendet wird, um einen MIME-Typ zusammen mit hochgeladenen Dateien zu senden. Sie können die Liste der von urlmon.dll unterstützten MIME-Typen anzeigen. Eine Sache, auf die Sie achten sollten, ist image/pjpeg und image/x-png, die nicht dem Standard entsprechen. In meinem Code ersetze ich diese durch image/jpeg und image/png.

19
mroach

Sie können es nicht aus dem Bytestrom erkennen, aber Sie können den MIME-Typ speichern, wenn Sie den byte[] zum ersten Mal auffüllen.

8
user114600

Kurze Antwort: Das geht nicht

Längere Antwort: Normalerweise verwenden Programme die Dateierweiterung, um zu wissen, um welche Art von Datei es sich handelt. Wenn Sie diese Erweiterung nicht haben, können Sie nur Vermutungen anstellen. Beispielsweise könnten Sie die ersten Bytes überprüfen und prüfen, ob Sie einen bekannten Header (beispielsweise XML-Deklarationstag oder Bitmap- oder JPEG-Header) erkennen ). Aber das wird am Ende immer eine Vermutung sein: Ohne einige Metadaten oder Informationen über den Inhalt ist ein Array von Bytes nur bedeutungslos ...

7
Thomas Levesque

Wenn Sie wissen, dass es sich um einen System.Drawing.Image handelt, können Sie Folgendes tun:

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

Erinnert mich an den Tag, an dem wir, ähm "einige Leute", 50MB-Rar-Dateien auf den frühen kostenlosen Image-Hosting-Sites gemeinsam benutzten, indem sie einfach die .gif-Erweiterung zum .rar-Dateinamen hinzufügen. 

Wenn Sie sich öffentlich gegenüberstehen und einen bestimmten Dateityp erwarten, und Sie müssen sicherstellen, dass es sich um diesen Dateityp handelt, können Sie der Erweiterung nicht einfach vertrauen. 

Wenn Ihre App jedoch keinen Grund hat, der hochgeladenen Erweiterung und/oder dem MIME-Typ zu misstrauen, dann holen Sie sich diese einfach, wenn die Datei hochgeladen wird, wie die Antworten, die Sie von @rossfabircant und @RandolphPotter erhalten haben. Erstellen Sie einen Typ, der das Byte [] sowie die ursprüngliche Erweiterung oder den Mimetyp enthält, und geben Sie diesen weiter.

Wenn Sie sicherstellen müssen, dass es sich bei der Datei tatsächlich um einen bestimmten erwarteten Typ handelt, beispielsweise um ein gültiges .jpeg oder .png, können Sie versuchen, die Datei als diese Typen zu interpretieren und zu sehen, ob sie erfolgreich geöffnet wird. (System.Drawing.Imaging.ImageFormat)

Wenn Sie versuchen, die Datei nur aus den binären Inhalten zu klassifizieren, und dies könnte ein beliebiges Format in der ganzen Welt sein, ist dies ein hartes, offenes Problem, und es gibt keine 100% zuverlässige Methode. Sie könnten TrID dagegen anrufen, und es gibt wahrscheinlich ähnliche Forensik-Tools, die von Strafverfolgungs-Ermittlern verwendet werden, wenn Sie sie finden (und sich leisten können).

Wenn Sie es nicht auf die harte Tour tun müssen, tun Sie es nicht.

2
DanO

Du willst es nicht so machen. Rufen Sie Path.GetExtension auf, wenn die Datei hochgeladen wird, und übergeben Sie die Erweiterung mit dem Byte [].

1
RossFabricant

Mit der Eigenschaft "RawFormat.Guid" von System.Drawing.Image können Sie den MIME-Typ von Images erkennen.

aber ich bin nicht sicher, wie ich andere Dateitypen finden kann.

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

UPDATE: Sie können versuchen, einen Blick auf diesen Beitrag zu werfen

Wie finde ich mit .NET den Mime-Typ einer Datei anhand der Dateisignatur und nicht der Erweiterung

Wenn Sie nur eine begrenzte Anzahl erwarteter Dateitypen unterstützen möchten, können Sie mit magischen Zahlen arbeiten.

Eine einfache Methode zum Überprüfen ist das Öffnen von Beispieldateien mit einem Text-/Hex-Editor und das Untersuchen der führenden Bytes, um festzustellen, ob etwas vorhanden ist, mit dem Sie Dateien von den unterstützten Gruppen unterscheiden bzw. verwerfen können.

Wenn Sie dagegen nach einem beliebigen Dateityp suchen, ist dies, wie jeder bereits gesagt hat, hart.

0
Oskuro

Wenn Sie die Erweiterung des Dateinamens kennen, wird möglicherweise System.Web.MimeMapping den Trick ausführen:

MimeMapping.GetMimeMapping(fileDisplayNameWithExtension)

Ich habe es in MVC Action so verwendet:

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