3


2

VB.NETのファイルタイプチェック?

画像のサイズを変更したプログラムがあり、動作します。 問題は、ユーザーがファイル選択ダイアログで非画像ファイルを選択すると、クラッシュすることです。 画像ファイルを確認するにはどうすればよいですか?

5 Answer


7


OPがVBバージョンを主張していたため、https://stackoverflow.com/questions/3557874/filetype-check-in-vb-net/3557926#3557926 [0xA3’s answer]と同等のVB.NETを次に示します。

Function IsValidImage(filename As String) As Boolean
    Try
        Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename)
    Catch generatedExceptionName As OutOfMemoryException
        ' Image.FromFile throws an OutOfMemoryException
        ' if the file does not have a valid image format or
        ' GDI+ does not support the pixel format of the file.
        '
        Return False
    End Try
    Return True
End Function

次のように使用します。

If IsValidImage("c:\path\to\your\file.ext") Then
    'do something
    '
Else
    'do something else
    '
End If

'' '' '

編集: +ファイル拡張子を確認することはお勧めしません。 誰でも、 `.jpg`拡張子を持つ別のファイル(たとえば、テキストドキュメント)を保存し、アプリをだましてそれを画像にすることができます。

最良の方法は、上記の関数を使用して画像を読み込むか、最初の数バイトを開いてJPEG署名を確認することです。

 +
 +
JPEGファイルとそのヘッダーの詳細については、次を参照してください。


5


非常に原始的なチェックは、単にイメージをロードしようとすることです。 有効でない場合、「OutOfMemoryException」がスローされます:

static bool IsImageValid(string filename)
{
    try
    {
        System.Drawing.Image img = System.Drawing.Image.FromFile(filename);
    }
    catch (OutOfMemoryException)
    {
        // Image.FromFile throws an OutOfMemoryException
        // if the file does not have a valid image format or
        // GDI+ does not support the pixel format of the file.
        //
        return false;
    }
    return true;
}

あなたの質問があなたのアプリケーションを正しく理解していれば、とにかく画像をロードします。 したがって、ロード操作をtry / catchブロックで単にラップするだけでは、追加のオーバーヘッドは発生しません。 このアプローチのVB.NETソリューションについては、@ Alex Essilfieによる回答を確認してください。

なぜImage.FromFileが無効なファイルに対してOOMをスローするのか疑問に思う人は、次の質問に対するhttps://stackoverflow.com/users/17034/hans-passant[Hans Passant]の答えを読むべきです。

_ * https://stackoverflow.com/questions/2610416/is-there-a-reason-image-fromfile-throws-an-outofmemoryexception-for-an-invalid-im [Image.FromFileがOutOfMemoryExceptionをスローする理由があります無効な画像形式ですか?] * _


3


もちろん、最初の防衛線は、ファイルの拡張子を確認することです。

Function IsImageFile(ByVal filename As String) As Boolean
    Dim ext As String = Path.GetExtension(filename).ToLowerInvariant()

    ' This supposes your program can deal only with JPG files; '
    ' you could add other extensions here as necessary. '
    Return ext = ".jpg" OrElse ext = ".jpeg"
End Function

さらに良いことに、SLCがコメントで示唆しているように、ダイアログの `Filter`プロパティを設定します。

dialog.Filter = "Image files|*.jpg;*.jpeg"

これは保証ではありません-理想的には、ファイル自体をチェックして画像であることを確認したいと思います。理論的には、実際に画像ファイルである場合は異常な拡張子を持つファイルもロードできるはずです(単にユーザーの最初の承認)-しかし、それは簡単なスタートです。


2


VBとC#の回答は素晴らしいですが、ファイルを変更または移動する予定がある場合は "gotcha"も含まれます。作成された 'img’オブジェクトは、dispose()メソッドを呼び出して解放しない限り、イメージファイルをロックします。 下記参照:

VB
    Function IsValidImage(filename As String) As Boolean
    Try
        Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename)
        img.dispose()  ' Removes file-lock of IIS
    Catch generatedExceptionName As OutOfMemoryException
        ' Image.FromFile throws an OutOfMemoryException
        ' if the file does not have a valid image format or
        ' GDI+ does not support the pixel format of the file.
        '
        Return False
    End Try
    Return True
End Function

C#
static bool IsImageValid(string filename)
{
    try
    {
        System.Drawing.Image img = System.Drawing.Image.FromFile(filename);
        img.dispose();   // Removes file-lock of IIS
    }
    catch (OutOfMemoryException)
    {
        // Image.FromFile throws an OutOfMemoryException
        // if the file does not have a valid image format or
        // GDI+ does not support the pixel format of the file.
        //
        return false;
    }
    return true;
}


0


最も堅牢な方法は、ロードする必要があるファイルの署名を理解することです。

たとえば、JPEGには特定のヘッダー形式があります。

このようにして、拡張機能を見るだけでコードが簡単にだまされることはありません。

163の答えは、これらの線に沿ってほとんどの方法を取得する必要があります。