web-dev-qa-db-ja.com

C#では、byte []からファイルの種類をどのようにして知ることができますか?

アップロードされたファイルから満たされたバイト配列があります。ただし、コードの別の部分では、正しいコンテンツタイプをブラウザーにレンダリングできるように、byte []からアップロードされたこのファイルタイプを知る必要があります。

ありがとう!!

28
AndreMiranda

確かではありませんが、おそらく マジックナンバー について調査する必要があります。

更新:それについて読んで、私はそれが非常に信頼できるとは思いません。

9
Carles Company

前述のように、MIMEマジックはこれを行う唯一の方法です。多くのプラットフォームでは、これを効率的に行うために、最新の堅牢なMIMEマジックファイルとコードが提供されています。サードパーティのコードなしで.NETでこれを行う唯一の方法は、urlmon.dllからFindMimeFromDataを使用することです。方法は次のとおりです。

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

これは、Internet Explorer MIME検出器を使用します。これは、IEがMIMEタイプをアップロードされたファイルと一緒に送信するために使用するコードと同じです。 rlmon.dllがサポートするMIMEタイプのリスト を確認できます。注意が必要なのはimage/pjpegimage/x-pngで、これらは非標準です。私のコードでは、これらをimage/jpegimage/pngに置き換えます。

20
mroach

バイトストリームからはわかりませんが、byte[]に最初にデータを入力するときにMIMEタイプを保存できます。

8
user114600

短い答え:できません

より長い答え:通常、プログラムはファイル拡張子を使用して、処理するファイルの種類を認識します。その拡張子がない場合は、推測しかできません...たとえば、最初の数バイトを見て、よく知られているヘッダー(たとえば、XML宣言タグ、またはビットマップまたはJPEGヘッダー)を認識しているかどうかを確認できます。 )。しかし、それは結局のところ推測です。メタデータやコンテンツに関する情報がなければ、バイトの配列は意味がありません...

7
Thomas Levesque

あなたが知っているなら System.Drawing.Image 、次のことができます:

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

ファイル名の拡張子がわかっている場合は、System.Web.MimeMappingがトリックを実行する可能性があります。

MimeMapping.GetMimeMapping(fileDisplayNameWithExtension)

私は次のようにMVCアクションで使用しました:

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

昔のことを思い出します。私たち「えーと、何人か」は、.rarファイル名に.gif拡張子を追加するだけで、初期の無料画像ホスティングサイトで50MBのrarファイルを共有していました。

明らかに、あなたが公に直面していて、特定のファイルタイプを期待していて、それがそのファイルタイプであることを確認する必要があるなら、あなたは単に拡張子を信頼することはできません。

一方、アップロードされた拡張子やMIMEタイプをアプリが信頼できない理由がない場合は、@ rossfabircantや@RandolphPotterから受け取った回答と同様に、ファイルがアップロードされたときにそれらを取得します。元の拡張子またはmimetypeだけでなく、byte []を持つ型を作成し、それを渡します。

ファイルが実際に有効な.jpegや.pngなどの特定の予期されるタイプであることを確認する必要がある場合は、ファイルをそれらのタイプとして解釈して、正常に開くかどうかを確認できます。 (System.Drawing.Imaging.ImageFormat)

バイナリコンテンツのみからファイルを分類しようとしていて、それが全世界のあらゆる形式である可能性がある場合、これは本当に難しい、オープンエンドの問題であり、100%信頼できる方法はありません。あなたはそれに対して TrID を呼び出すことができ、それらを見つけられる(そして買うことができる)ならば、法執行機関の調査官が使用する同様の科学捜査ツールが存在する可能性があります。

難しい方法で行う必要がない場合は、行わないでください。

2
DanO

あなたはそれをそのようにしたくないのです。ファイルのアップロード時にPath.GetExtensionを呼び出し、byte []で拡張子を渡します。

1
RossFabricant

System.Drawing.Image 'RawFormat.Guid'プロパティを使用すると、画像のMIMEタイプを検出できます。

しかし、私は他のファイルタイプを見つける方法がわかりません。

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

UPDATE:あなたはこの投稿を見てみることができます

。NETを使用して、拡張子ではなくファイル署名に基づいてファイルのMIMEタイプをどのように見つけることができますか

サポートしたいファイルタイプの数が限られている場合は、マジックナンバーが適しています。

チェックする簡単な方法は、テキスト/ 16進エディタでサンプルファイルを開き、先頭のバイトを調べて、サポートされているセットからファイルを区別/破棄するために使用できるものが存在するかどうかを確認することです。

一方、誰もがすでに述べたように、任意のファイルタイプを認識することを望んでいる場合は難しいです。

0
Oskuro