【问题标题】:Get a MIME Type from a extension in C++从 C++ 中的扩展中获取 MIME 类型
【发布时间】:2023-03-08 22:20:01
【问题描述】:

在给定文件扩展名的情况下,有什么方法可以在 C++ 中获取 MIME 类型?

我已经阅读了有关 HKEY_CLASSES_ROOT 的信息,但我真的不知道如何使用它。

我想要的是输入:

 string extension=".pdf"; 
 string extension2=".avi";

获取输出:

字符串 mimeType="application/pdf";
字符串 mimeType2="video/x-msvideo";

我知道我可以自己完成,但我想这里已经完成了一些工作。

非常感谢

【问题讨论】:

标签: c++ windows winapi


【解决方案1】:

快到圣诞节了,这样怎么样:

#include <Windows.h>
#include <string>

using namespace std;

string GetMimeType(const string &szExtension)
{
    // return mime type for extension
    HKEY hKey = NULL;
    string szResult = "application/unknown";

    // open registry key
    if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szExtension.c_str(), 
                       0, KEY_READ, &hKey) == ERROR_SUCCESS)
    {
        // define buffer
        char szBuffer[256] = {0};
        DWORD dwBuffSize = sizeof(szBuffer);

        // get content type
        if (RegQueryValueEx(hKey, "Content Type", NULL, NULL, 
                       (LPBYTE)szBuffer, &dwBuffSize) == ERROR_SUCCESS)
        {
            // success
            szResult = szBuffer;
        }

        // close key
        RegCloseKey(hKey);
    }

    // return result
    return szResult;
}

int main(int argc, char* argv[])
{
    string szExt1 = ".pdf";
    string szExt2 = ".avi";

    string szMime1 = GetMimeType(szExt1);
    string szMime2 = GetMimeType(szExt2);

    printf("%s = %s\n%s = %s\n", szExt1.c_str(), szMime1.c_str(), 
        szExt2.c_str(), szMime2.c_str());

    return 0;
}

在我的系统上,它给出以下输出:

.pdf = 应用程序/pdf
.avi = 视频/avi

【讨论】:

  • 感谢您抽出宝贵时间罗杰,我得到了意想不到的输出,但会更深入地检查;)
  • @user3009804 好的 - 如果我能提供进一步的帮助,请告诉我(当我仍然感觉圣诞节时)。正如您在问题中使用 string 一样,我做了一个非 UNICODE 示例。
  • 下午好,罗杰,我已经尝试了你的非 UNICODE 代码以及 IInspectable 的代码,我发现使用你的代码我可以获得一些扩展的 MIME 类型,但我不能其他扩展。例如,我知道该应用程序是未知的,扩展名为:.avi、.mp3。 .mp4, .wmv, .rar, .log, .... 你知道有什么问题吗?谢谢大家;)
  • @user3009804 - 它只是在读取注册表,因此请使用 Regedit.exe 查看例如HKEY_CLASSES_ROOT\.mp3 并查看是否有Content Type 键。如果有,可能是权限问题。 HKEY_CLASSES_ROOT\MIME\Database\Content Type 也有反向查询。
  • @user3009804 你知道将我的方法与 IInspectable 结合起来可能是值得的——据我所知,他只会给出 26 个(左右)预定义类型,而我只会给出扩展名所在的那些通过应用程序注册。如果一个失败,另一个可能会成功。
【解决方案2】:

最简单的解决方案是调用FindMimeFromData

#include <urlmon.h>
#pragma comment( lib, "urlmon" )

std::wstring MimeTypeFromString( const std::wstring& str ) {

    LPWSTR pwzMimeOut = NULL;
    HRESULT hr = FindMimeFromData( NULL, str.c_str(), NULL, 0,
                                   NULL, FMFD_URLASFILENAME, &pwzMimeOut, 0x0 );
    if ( SUCCEEDED( hr ) ) {
        std::wstring strResult( pwzMimeOut );
        // Despite the documentation stating to call operator delete, the
        // returned string must be cleaned up using CoTaskMemFree
        CoTaskMemFree( pwzMimeOut );
        return strResult;
    }

    return L"";
}

以下应用程序

int _tmain( int argc, _TCHAR* argv[] ) {
    std::wcout << L".pdf: " << MimeTypeFromString( L".pdf" ) << std::endl;
    std::wcout << L".avi: " << MimeTypeFromString( L".avi" ) << std::endl;

    return 0;
}

在我的系统上产生这个输出:

.pdf: application/pdf
.avi: video/avi

【讨论】:

  • 非常感谢您的代码!我已经尝试使用几个扩展名,其中一些有效,而另一些则无效,例如 .avi(是的,不明白 .avi 怎么不能工作)、.mov、.mp3、.mp4 等。 mpeg, .vmw, ...你知道会发生什么吗?非常感谢!
  • 从我在一个紧密循环中进行的一些测试中(使用任务管理器查看while (true) {}))我同意CoTaskMemFree
猜你喜欢
  • 2010-11-05
  • 2015-06-13
  • 2013-11-10
  • 2013-09-11
  • 2019-09-24
  • 2014-06-14
  • 2012-04-05
相关资源
最近更新 更多