从 C++ 中的扩展中获取 MIME 类型

Posted

技术标签:

【中文标题】从 C++ 中的扩展中获取 MIME 类型【英文标题】:Get a MIME Type from a extension in C++ 【发布时间】:2014-01-05 05:53:24 【问题描述】:

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

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

我想要的是输入:

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

获取输出:

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

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

非常感谢

【问题讨论】:

FindMimeFromData 【参考方案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

以上是关于从 C++ 中的扩展中获取 MIME 类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在不基于扩展的 IOS 中获取 Mime 类型

如何从 Java 中的 MIME 类型确定适当的文件扩展名

Laravel 4 中 File::mime() 的替换(从文件扩展名中获取 mime 类型)

Laravel 5 - 从文件扩展名中获取 MIME 类型

从文件扩展名中获取 MIME 类型

从文件扩展名中获取 MIME 类型