Почему FindMimeFromData распознает изображение / изображение на одном хосте, а не на другом? - PullRequest
4 голосов
/ 08 июля 2011

Я использую FindMimeFromData из urlmon.dll для прослушивания загруженных файлов MIME-типа. Согласно Обнаружение типов MIME в Internet Explorer , image/tiff является одним из распознанных типов MIME. Он отлично работает на моей машине для разработки (Windows 7 64bit, IE9), но не работает в тестовой среде (Windows Server 2003 R2 64bit, IE8) - он возвращает application/octet-stream вместо image/tiff.

В вышеприведенной статье описываются точные шаги, предпринятые для определения типа MIME, но, поскольку image/tiff является одним из 26 распознанных типов, он должен заканчиваться на шаге 2 (прослушивание фактических данных), чтобы расширения файлов и зарегистрированные приложения (и другие материалы реестра) не должны иметь значения.

Да, кстати, файлы TIFF на самом деле связаны с программой (Windows Picture and Fax Viewer) на тестовом сервере. Дело не в том, что в реестре 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);
    // ...
}

1 Ответ

5 голосов
/ 28 октября 2012

Мне не удалось воспроизвести вашу проблему, однако я провел некоторое исследование по этому вопросу. Я полагаю, что это, как вы подозреваете, проблема с шагом 2 в MIME Type Detection: жестко запрограммированные тесты в urlmon.dll v9 отличаются от тестов в urlmon.dll v8.

Статья в Википедии TIFF показывает, насколько сложен формат, и это было проблемой с самого начала:

Когда был представлен TIFF, его расширяемость вызывала проблемы совместимости. Гибкость кодирования породила шутку о том, что TIFF означает тысяч несовместимых форматов файлов .

В разделе TIFF Compression Tag четко показаны многие редкие схемы сжатия, которые, как я подозреваю, были опущены при создании жестко закодированных тестов urlmon.dll в более ранних версиях IE.

Итак, что можно сделать, чтобы решить эту проблему? Я могу придумать три решения, но каждое из них приносит новые виды проблем:

  1. Обновите IE на вашем компьютере разработчика до версии 9.
  2. Примените последние обновления IE 8 на своем компьютере разработчика. Хорошо известно, что часто вводятся модифицированные версии urlmon.dll (например, KB974455 ). Один из них может содержать обновленные жестко запрограммированные тесты MIME.
  3. Распространите собственную копию urlmon.dll с вашим приложением.

Кажется, вам следует выбрать решения 1 и 2. Однако может возникнуть проблема с производственной средой. Как показывает мой опыт, администраторы рабочей среды часто не соглашаются устанавливать некоторые обновления по многим причинам. Может быть, будет сложнее убедить администратора обновить IE до v9 и проще установить обновление IE8 KB (как и должно быть, но мы все знаем, как оно). Если вы контролируете производственную среду, я думаю, вам следует перейти к решению 1.

3-е решение вводит две проблемы:

  • законно: распространять собственную копию urlmon.dll может быть против политики Microsoft
  • кодирование: вам нужно динамически загрузить dll , чтобы вызвать функцию FindMimeFromData или хотя бы настроить файл манифеста вашего приложения из-за Порядка поиска библиотеки динамических ссылок . Я предполагаю, что вы знаете, что это очень плохая идея, просто вручную скопировать более новую версию urlmon.dll в системную папку, так как другие приложения, скорее всего, аварийно завершат работу при ее использовании.

В любом случае, удачи в разгадке загадки urlmon.

...