4

アップロードされたファイルのMIMEタイプをスニッフィングするためにFindMimeFromDatafromを使用しています。Internet ExplorerのMIMEタイプ検出にurlmon.dllよると、は認識されているMIMEタイプの1つです。私の開発マシン(Windows 7 64ビット、IE9)では正常に動作しますが、テスト環境(Windows Server 2003 R2 64ビット、IE8)では動作しません-の代わりに戻ります。image/tiffapplication/octet-streamimage/tiff

上記の記事では、MIMEタイプを判別するために実行する正確な手順について説明していますが、これimage/tiffは26の認識されたタイプの1つであるため、ステップ2(実際のデータをスニッフィング)で終了する必要があります。これにより、ファイル拡張子と登録済みアプリケーション(およびその他のレジストリ関連のもの)が関係ありません。

ちなみに、TIFFファイルは実際にテストサーバー上のプログラム(Windows画像とFAXビューア)に関連付けられています。WindowsレジストリにTIFFへの参照がないわけではありません。

期待どおりに機能しない理由はありますか?

編集: FindMimeFromDataは次のように使用されます:

public class MimeUtil
{
    [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
    private static extern int FindMimeFromData(
        IntPtr pBC,
        [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 3)] byte[] pBuffer,
        int cbSize,
        [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
        int dwMimeFlags,
        out IntPtr ppwzMimeOut,
        int dwReserved);

    public static string GetMimeFromData(byte[] data)
    {
        IntPtr mimetype = IntPtr.Zero;
        try
        {
            const int flags = 0x20; // FMFD_RETURNUPDATEDIMGMIMES
            int res = FindMimeFromData(IntPtr.Zero, null, data, data.Length, null, flags, out mimetype, 0);
            switch (res)
            {
                case 0:
                    string mime = Marshal.PtrToStringUni(mimetype);
                    return mime;
                // snip - error handling
                // ...
                default:
                    throw new Exception("Unexpected HRESULT " + res + " returned by FindMimeFromData (in urlmon.dll)");
            }
        }
        finally
        {
            if (mimetype != IntPtr.Zero)
                Marshal.FreeCoTaskMem(mimetype);
        }
    }
}

これは次のように呼ばれます:

protected void uploader_FileUploaded(object sender, FileUploadedEventArgs e)
{
    int bsize = Math.Min(e.File.ContentLength, 256);
    byte[] buffer = new byte[bsize];
    int nbytes = e.File.InputStream.Read(buffer, 0, bsize);
    if (nbytes > 0)
        string mime = MimeUtil.GetMimeFromData(buffer);
    // ...
}
4

1 に答える 1

5

私はあなたの問題を再現することができませんでした、しかし私は主題に関していくつかの研究をしました。ご想像のとおり、問題はMIMEタイプ検出のステップ2にあると思います。urlmon.dllv9のハードコードされたテストは、urlmon.dllv8のテストとは異なります。

TIFFに関するウィキペディアの記事は、フォーマットがいかに複雑であるかを示しており、それは最初から問題でした。

TIFFが導入されたとき、その拡張性は互換性の問題を引き起こしました。エンコーディングの柔軟性により、TIFFは数千の互換性のないファイル形式を表すというジョークが生まれました。

TIFF圧縮タグのセクションには、以前のバージョンのIEでハードコードされたurlmon.dllテストを作成する際に省略された、多くのまれな圧縮スキームが明確に示されています。

では、この問題を解決するために何ができるでしょうか?私は3つの解決策を考えることができますが、それぞれが異なる種類の新しい問題をもたらします。

  1. 開発マシンのIEをバージョン9に更新します。
  2. 開発マシンに最新のIE8アップデートを適用します。urlmon.dllの変更バージョンが頻繁に導入されることはよく知られています(例:KB974455)。それらの1つには、更新されたMIMEハードコードされたテストが含まれている場合があります。
  3. urlmon.dllの独自のコピーをアプリケーションと一緒に配布します。

ソリューション1と2が選択すべきもののようです。ただし、実稼働環境に問題がある可能性があります。私の経験が示すように、本番環境の管理者は、多くの理由でいくつかの更新をインストールすることに同意しないことがよくあります。管理者にIEをv9に更新するよう説得するのは難しいかもしれませんし、IE8 KB更新をインストールするのは簡単かもしれません(彼らはそうするはずですが、私たちは皆それがどのようであるかを知っています)。本番環境を管理している場合は、ソリューション1を使用する必要があると思います。

3番目の解決策では、次の2つの問題が発生します。

  • 合法:urlmon.dllの独自のコピーを配布することはMicrosoftのポリシーに違反する可能性があります
  • コーディング:関数を呼び出すにはdllを動的にロードするか、ダイナミックリンクライブラリの検索順序FindMimeFromDataのために少なくともアプリのマニフェストファイルをカスタマイズする必要があります。他のアプリがそれを使用してクラッシュする可能性が高いため、新しいバージョンのurlmon.dllをシステムフォルダに手動でコピーすることは非常に悪い考えであることをご存知だと思います。

とにかく、あなたのurlmonなぞなぞを解いて頑張ってください。

于 2012-10-28T12:26:15.237 に答える