MIME类型检测库

文章目录

  • [MIME类型检测库 - 代码介绍大纲](#MIME类型检测库 - 代码介绍大纲)
    • 一、项目概述
      • [1.1 项目目标](#1.1 项目目标)
      • [1.2 主要特性](#1.2 主要特性)
    • 二、核心接口设计
      • [2.1 抽象接口类 `IMimeTypeDetector`](#2.1 抽象接口类 IMimeTypeDetector)
      • [2.2 核心接口方法](#2.2 核心接口方法)
      • [2.3 工厂模式设计](#2.3 工厂模式设计)
    • 三、平台实现详情
      • [3.1 macOS实现 (`MacMimeTypeDetector`)](#3.1 macOS实现 (MacMimeTypeDetector))
      • [3.2 Windows实现 (`WindowsMimeTypeDetector`)](#3.2 Windows实现 (WindowsMimeTypeDetector))
      • [3.3 默认实现 (`DefaultMimeTypeDetector`)](#3.3 默认实现 (DefaultMimeTypeDetector))
    • 四、使用示例
      • [4.1 基本使用](#4.1 基本使用)
      • [4.2 高级使用场景](#4.2 高级使用场景)
    • 五、技术要点
      • [5.1 跨平台设计](#5.1 跨平台设计)
      • [5.2 资源管理](#5.2 资源管理)
      • [5.3 性能优化](#5.3 性能优化)
    • 六、扩展性设计
      • [6.1 添加新平台](#6.1 添加新平台)
      • [6.2 自定义魔术字节识别](#6.2 自定义魔术字节识别)
    • 七、依赖与编译
      • [7.1 macOS依赖](#7.1 macOS依赖)
      • [7.2 Windows依赖](#7.2 Windows依赖)
      • [7.3 编译配置](#7.3 编译配置)
    • 八、注意事项
      • [8.1 平台差异](#8.1 平台差异)
      • [8.2 权限要求](#8.2 权限要求)
      • [8.3 错误处理](#8.3 错误处理)
    • 九、未来扩展方向
  • 参考实现

MIME类型检测库 - 代码介绍大纲

一、项目概述

1.1 项目目标

  • 创建跨平台的文件MIME类型检测库

  • 支持多种检测方式(扩展名、文件内容、组合检测)

  • 提供统一的编程接口,屏蔽平台差异

1.2 主要特性

  • 支持Windows、macOS平台,可扩展其他平台

  • 提供文件路径、内存数据、文件描述符三种检测方式

  • 包含便捷的全局访问函数

  • 默认检测器提供基本功能,保证库的健壮性

二、核心接口设计

2.1 抽象接口类 IMimeTypeDetector

复制代码
// 检测方法枚举
enum DetectionMethod {
    METHOD_EXTENSION = 0,  // 基于扩展名
    METHOD_CONTENT,        // 基于文件内容
    METHOD_BOTH            // 两者结合
};

2.2 核心接口方法

  1. **GetMimeType()**​ - 通过文件路径检测MIME类型

  2. **GetMimeTypeFromMemory()**​ - 通过内存数据检测MIME类型

  3. **GetFileExtension()**​ - 提取文件扩展名

  4. **GetMimeTypeFromFD()**​ - 通过文件描述符检测MIME类型

2.3 工厂模式设计

  • CreateMimeTypeDetector()- 创建平台特定的检测器实例

  • 全局便捷函数封装,简化使用

三、平台实现详情

3.1 macOS实现 (MacMimeTypeDetector)

核心技术
  • 使用Uniform Type Identifiers (UTI)系统

  • 依赖CoreFoundation/CoreServices框架

  • 文件扩展名与MIME类型映射

关键方法
  1. UTI查询 ​ - 通过UTTypeCopyPreferredTagWithClass()获取MIME类型

  2. 内容检测​ - 读取文件属性或魔术字节识别

  3. 文件描述符处理​ - 支持已打开文件的类型检测

3.2 Windows实现 (WindowsMimeTypeDetector)

核心技术
  • Windows文件关联API (AssocQueryStringW)

  • URL Moniker API (FindMimeFromData)

  • Shell路径处理函数

关键方法
  1. 注册表查询​ - 通过扩展名获取关联的MIME类型

  2. 内容探测​ - 使用Windows内置的MIME类型检测

  3. 编码转换​ - UTF-8与UTF-16字符串转换

3.3 默认实现 (DefaultMimeTypeDetector)

  • 提供基本接口实现

  • 保证代码在未实现平台上的可编译性

  • 返回通用类型application/octet-stream

四、使用示例

4.1 基本使用

复制代码
// 方式1:使用全局函数
std::string mime = GetMimeType("test.pdf");

// 方式2:创建检测器实例
auto detector = CreateMimeTypeDetector();
std::string mime = detector->GetMimeType("test.jpg", 
    IMimeTypeDetector::METHOD_BOTH);

4.2 高级使用场景

复制代码
// 内存数据检测
std::vector<BYTE> data = {0x89, 0x50, 0x4E, 0x47}; // PNG魔术字节
std::string mime = GetMimeTypeFromMemory(
    data.data(), 
    data.size(), 
    "image.png");

// 文件描述符检测
int fd = open("test.txt", O_RDONLY);
std::string mime = GetMimeTypeFromFD(fd, "test.txt");

五、技术要点

5.1 跨平台设计

  • 条件编译处理平台差异

  • 统一的接口设计

  • 智能指针管理资源

5.2 资源管理

  • RAII原则管理平台资源

  • 正确的内存释放

  • 错误处理机制

5.3 性能优化

  • 缓存读取位置(文件描述符检测)

  • 最小化数据读取

  • 平台原生API调用

六、扩展性设计

6.1 添加新平台

  1. 继承IMimeTypeDetector接口

  2. 实现所有纯虚函数

  3. 更新平台检测逻辑

  4. 修改CreateMimeTypeDetector()工厂函数

6.2 自定义魔术字节识别

  • 扩展DetectMimeTypeFromData()方法

  • 添加新的文件格式支持

  • 维护扩展的MIME类型映射

七、依赖与编译

7.1 macOS依赖

  • CoreFoundation.framework

  • CoreServices.framework

  • UniformTypeIdentifiers.framework (macOS 11+)

7.2 Windows依赖

  • Windows SDK

  • urlmon.lib

  • shlwapi.lib

  • COM初始化要求

7.3 编译配置

复制代码
# 示例CMake配置
set(PLATFORM_MAC 0)  # 根据目标平台设置
set(PLATFORM_WINDOWS 1)

八、注意事项

8.1 平台差异

  • Windows需要COM初始化

  • macOS的UTI系统在旧版本中行为不同

  • 文件描述符在Windows和POSIX系统中的差异

8.2 权限要求

  • 文件读取权限

  • Windows注册表查询权限

  • 内存访问权限

8.3 错误处理

  • 返回默认MIME类型application/octet-stream

  • 资源分配失败处理

  • API调用错误处理

九、未来扩展方向

  1. 添加Linux平台支持(使用libmagic/file命令)

  2. 支持自定义MIME类型映射

  3. 添加异步检测接口

  4. 增加缓存机制提升性能

  5. 支持更多文件格式的魔术字节检测


最后更新: 2025-01-05

版本: 1.0.0

作者: 跨平台开发团队

参考实现

cpp 复制代码
//#include "BaseDataType.h"

#define PLATFORM_WINDOWS 1




#include <string>

#include <memory>

#include <vector>




// 定义统一的MimeTypeDetector接口类

class IMimeTypeDetector {

public:

    enum DetectionMethod {

        METHOD_EXTENSION = 0,    // 基于扩展名

        METHOD_CONTENT,          // 基于文件内容

        METHOD_BOTH              // 两者结合

    };




    virtual ~IMimeTypeDetector() = default;




    // 统一的接口函数

    virtual std::string GetMimeType(const std::string& file_path,

        DetectionMethod method = METHOD_BOTH) = 0;




    virtual std::string GetMimeTypeFromMemory(const unsigned char* data,

        size_t data_size,

        const std::string& file_name = "",

        const std::string& file_ext = "") = 0;




    virtual std::string GetFileExtension(const std::string& file_name) = 0;




    virtual std::string GetMimeTypeFromFD(int fd,

        const std::string& file_name = "") = 0;

};




// 辅助函数:获取平台特定的检测器实例

std::unique_ptr<IMimeTypeDetector> CreateMimeTypeDetector();




// 全局便捷访问函数

inline std::string GetMimeType(const std::string& file_path,

    IMimeTypeDetector::DetectionMethod method = IMimeTypeDetector::METHOD_BOTH) {

    auto detector = CreateMimeTypeDetector();

    return detector->GetMimeType(file_path, method);

}




inline std::string GetMimeTypeFromMemory(const unsigned char* data,

    size_t data_size,

    const std::string& file_name = "",

    const std::string& file_ext = "") {

    auto detector = CreateMimeTypeDetector();

    return detector->GetMimeTypeFromMemory(data, data_size, file_name, file_ext);

}




inline std::string GetFileExtension(const std::string& file_name) {

    auto detector = CreateMimeTypeDetector();

    return detector->GetFileExtension(file_name);

}




inline std::string GetMimeTypeFromFD(int fd,

    const std::string& file_name = "") {

    auto detector = CreateMimeTypeDetector();

    return detector->GetMimeTypeFromFD(fd, file_name);

}




// 平台特定的实现

#if PLATFORM_MAC




#include <cstring>

#include <CoreFoundation/CoreFoundation.h>

#include <CoreServices/CoreServices.h>

#include <UniformTypeIdentifiers/UniformTypeIdentifiers.h>

#include <unistd.h>




class MacMimeTypeDetector : public IMimeTypeDetector {

public:

    // 移除override关键字,使用正确的签名

    std::string GetMimeType(const std::string& file_path,

        DetectionMethod method = METHOD_BOTH) {

        std::string mime_type = "application/octet-stream";




        CFStringRef cf_path = CFStringCreateWithCString(kCFAllocatorDefault,

            file_path.c_str(),

            kCFStringEncodingUTF8);

        if (!cf_path) {

            return mime_type;

        }




        CFURLRef file_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,

            cf_path,

            kCFURLPOSIXPathStyle,

            false);

        CFRelease(cf_path);




        if (!file_url) {

            return mime_type;

        }




        mime_type = GetMimeTypeFromURL(file_url, method);

        CFRelease(file_url);




        return mime_type;

    }




    std::string GetMimeTypeFromMemory(const unsigned char* data,

        size_t data_size,

        const std::string& file_name = "",

        const std::string& file_ext = "") {

        std::string mime_type = "application/octet-stream";




        // 如果有扩展名,先尝试通过扩展名获取

        std::string ext = file_ext;

        if (ext.empty() && !file_name.empty()) {

            ext = GetFileExtension(file_name);

        }




        if (!ext.empty()) {

            CFStringRef cf_ext = CFStringCreateWithCString(kCFAllocatorDefault,

                ext.c_str(),

                kCFStringEncodingUTF8);

            if (cf_ext) {

                CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,

                    cf_ext,

                    nullptr);

                CFRelease(cf_ext);




                if (uti) {

                    mime_type = GetMimeTypeFromUTI(uti);

                    CFRelease(uti);




                    if (mime_type != "application/octet-stream") {

                        return mime_type;

                    }

                }

            }

        }




        // 通过内容检测

        if (data && data_size > 0) {

            mime_type = DetectMimeTypeFromData(data, data_size);

        }




        return mime_type;

    }




    std::string GetFileExtension(const std::string& file_name) {

        size_t dot_pos = file_name.find_last_of('.');

        if (dot_pos != std::string::npos && dot_pos < file_name.length() - 1) {

            return file_name.substr(dot_pos + 1);

        }

        return "";

    }




    std::string GetMimeTypeFromFD(int fd,

        const std::string& file_name = "") {

        std::string mime_type = "application/octet-stream";




        // 读取文件头

        unsigned char buffer[4096];

        ssize_t bytes_read = read(fd, buffer, sizeof(buffer));




        // 恢复文件指针

        if (bytes_read > 0) {

            lseek(fd, -bytes_read, SEEK_CUR);

            mime_type = GetMimeTypeFromMemory(buffer, bytes_read, file_name);

        }




        return mime_type;

    }




private:

    std::string GetMimeTypeFromURL(CFURLRef file_url, DetectionMethod method) {

        std::string mime_type = "application/octet-stream";




        // 先尝试通过扩展名获取

        if (method == METHOD_EXTENSION || method == METHOD_BOTH) {

            CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,

                nullptr,

                file_url);

            if (uti) {

                mime_type = GetMimeTypeFromUTI(uti);

                CFRelease(uti);

            }

        }




        // 如果需要通过内容检测

        if (method == METHOD_CONTENT ||

            (method == METHOD_BOTH && mime_type == "application/octet-stream")) {

            CFStringRef keys[] = { kCFURLTypeIdentifierKey };

            CFArrayRef key_array = CFArrayCreate(kCFAllocatorDefault,

                (const void**)keys, 1,

                &kCFTypeArrayCallBacks);




            CFErrorRef error = nullptr;

            CFDictionaryRef attrs = CFURLCopyResourcePropertiesForKeys(file_url,

                key_array,

                &error);

            CFRelease(key_array);




            if (attrs) {

                CFStringRef uti = static_cast<CFStringRef>(

                    CFDictionaryGetValue(attrs, kCFURLTypeIdentifierKey));

                if (uti) {

                    CFRetain(uti);

                    std::string content_mime = GetMimeTypeFromUTI(uti);

                    CFRelease(uti);




                    if (!content_mime.empty() &&

                        content_mime != "application/octet-stream") {

                        mime_type = content_mime;

                    }

                }

                CFRelease(attrs);

            }




            if (error) {

                CFRelease(error);

            }

        }




        return mime_type;

    }




    std::string GetMimeTypeFromUTI(CFStringRef uti) {

        std::string mime_type = "application/octet-stream";




        if (!uti) {

            return mime_type;

        }




        CFStringRef mime = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);

        if (mime) {

            char buffer[256];

            if (CFStringGetCString(mime, buffer, sizeof(buffer), kCFStringEncodingUTF8)) {

                mime_type = buffer;

            }

            CFRelease(mime);

        }




        return mime_type;

    }




    std::string DetectMimeTypeFromData(const unsigned char* data, size_t data_size) {

        std::string mime_type = "application/octet-stream";




        // 简单的魔术字节检测

        if (data_size >= 8) {

            if (data_size >= 4 && data[0] == 0x25 && data[1] == 0x50 &&

                data[2] == 0x44 && data[3] == 0x46) {

                return "application/pdf";

            }

            else if (data_size >= 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF) {

                return "image/jpeg";

            }

            else if (data_size >= 8 && data[0] == 0x89 && data[1] == 0x50 &&

                data[2] == 0x4E && data[3] == 0x47 && data[4] == 0x0D &&

                data[5] == 0x0A && data[6] == 0x1A && data[7] == 0x0A) {

                return "image/png";

            }

            else if (data_size >= 6 && data[0] == 0x47 && data[1] == 0x49 &&

                data[2] == 0x46 && data[3] == 0x38) {

                return "image/gif";

            }

            else if (data_size >= 2 && data[0] == 0x42 && data[1] == 0x4D) {

                return "image/bmp";

            }

        }




        return mime_type;

    }

};




// 创建Mac平台检测器

std::unique_ptr<IMimeTypeDetector> CreateMimeTypeDetector() {

    return std::make_unique<MacMimeTypeDetector>();

}




#elif PLATFORM_WINDOWS




#include <windows.h>

#include <urlmon.h>

#include <shlwapi.h>

#include <io.h>

#pragma comment(lib, "urlmon.lib")

#pragma comment(lib, "shlwapi.lib")




class WindowsMimeTypeDetector : public IMimeTypeDetector {

public:

    // 移除override关键字,使用正确的签名

    std::string GetMimeType(const std::string& file_path,

        DetectionMethod method = METHOD_BOTH) {

        std::wstring w_file_path = StringToWString(file_path);

        std::wstring mime_type = L"application/octet-stream";




        if (method == METHOD_EXTENSION || method == METHOD_BOTH) {

            mime_type = GetByExtension(w_file_path);

        }




        // 如果基于扩展名没找到,或者需要基于内容

        if (mime_type == L"application/octet-stream" ||

            method == METHOD_CONTENT) {

            std::wstring content_type = GetByContent(w_file_path);

            if (!content_type.empty() &&

                content_type != L"application/octet-stream") {

                mime_type = content_type;

            }

        }




        return WStringToString(mime_type);

    }




    std::string GetMimeTypeFromMemory(const unsigned char* data,

        size_t data_size,

        const std::string& file_name = "",

        const std::string& file_ext = "") {

        std::wstring w_file_name = StringToWString(file_name);

        std::wstring w_file_ext = StringToWString(file_ext);

        std::wstring mime_type = L"application/octet-stream";




        // 如果有扩展名,先尝试通过扩展名获取

        if (!w_file_ext.empty() || !w_file_name.empty()) {

            std::wstring ext = w_file_ext;

            if (ext.empty() && !w_file_name.empty()) {

                LPCWSTR ext_ptr = PathFindExtensionW(w_file_name.c_str());

                if (ext_ptr && wcslen(ext_ptr) > 0) {

                    ext = ext_ptr;

                }

            }




            if (!ext.empty()) {

                wchar_t buffer[MAX_PATH] = { 0 };

                DWORD size = MAX_PATH;




                if (SUCCEEDED(AssocQueryStringW(0, ASSOCSTR_CONTENTTYPE,

                    ext.c_str(), nullptr,

                    buffer, &size))) {

                    mime_type = buffer;

                }

            }

        }




        // 如果基于扩展名没找到,或者扩展名为空,则通过内容检测

        if (mime_type == L"application/octet-stream" ||

            (w_file_ext.empty() && w_file_name.empty())) {

            std::wstring content_type = GetByContentFromMemory(

                reinterpret_cast<const BYTE*>(data),

                data_size,

                w_file_name);

            if (!content_type.empty() &&

                content_type != L"application/octet-stream") {

                mime_type = content_type;

            }

        }




        return WStringToString(mime_type);

    }




    std::string GetFileExtension(const std::string& file_name) {

        size_t dot_pos = file_name.find_last_of('.');

        if (dot_pos != std::string::npos && dot_pos < file_name.length() - 1) {

            return file_name.substr(dot_pos + 1);

        }

        return "";

    }




    std::string GetMimeTypeFromFD(int fd,

        const std::string& file_name = "") {

        // 在Windows上,文件描述符需要转换为HANDLE

        HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));

        if (file_handle == INVALID_HANDLE_VALUE || !file_handle) {

            return "application/octet-stream";

        }




        // 保存当前位置

        DWORD current_pos = SetFilePointer(file_handle, 0, nullptr, FILE_CURRENT);




        // 读取数据

        BYTE buffer[4096];

        DWORD bytes_read = 0;

        BOOL success = ReadFile(file_handle, buffer, sizeof(buffer),

            &bytes_read, nullptr);




        // 恢复位置

        SetFilePointer(file_handle, current_pos, nullptr, FILE_BEGIN);




        if (!success || bytes_read == 0) {

            return "application/octet-stream";

        }




        std::wstring w_file_name = StringToWString(file_name);

        std::wstring w_mime_type = GetByContentFromMemory(buffer, bytes_read, w_file_name);

        return WStringToString(w_mime_type);

    }




private:

    std::wstring GetByExtension(const std::wstring& file_path) {

        LPCWSTR ext = PathFindExtensionW(file_path.c_str());

        if (!ext || wcslen(ext) == 0) {

            return L"application/octet-stream";

        }




        wchar_t buffer[MAX_PATH] = { 0 };

        DWORD size = MAX_PATH;




        if (SUCCEEDED(AssocQueryStringW(0, ASSOCSTR_CONTENTTYPE,

            ext, nullptr, buffer, &size))) {

            return buffer;

        }




        return L"application/octet-stream";

    }




    std::wstring GetByContent(const std::wstring& file_path) {

        HANDLE hFile = CreateFileW(file_path.c_str(), GENERIC_READ,

            FILE_SHARE_READ, nullptr,

            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

        if (hFile == INVALID_HANDLE_VALUE) {

            return L"";

        }




        BYTE buffer[4096];

        DWORD bytes_read = 0;

        std::wstring mime_type = L"";




        if (ReadFile(hFile, buffer, sizeof(buffer), &bytes_read, nullptr) &&

            bytes_read > 0) {

            LPWSTR pwz_mime = nullptr;

            HRESULT hr = FindMimeFromData(nullptr,

                file_path.c_str(),

                buffer,

                bytes_read,

                nullptr,

                0,

                &pwz_mime,

                0);




            if (SUCCEEDED(hr) && pwz_mime) {

                mime_type = pwz_mime;

                CoTaskMemFree(pwz_mime);

            }

        }




        CloseHandle(hFile);

        return mime_type.empty() ? L"application/octet-stream" : mime_type;

    }




    std::wstring GetByContentFromMemory(const BYTE* data,

        size_t data_size,

        const std::wstring& file_name) {

        if (!data || data_size == 0) {

            return L"application/octet-stream";

        }




        std::wstring mime_type = L"application/octet-stream";

        DWORD read_size = static_cast<DWORD>(data_size > 4096 ? 4096 : data_size);




        std::vector<BYTE> mutable_buffer(data, data + read_size);




        LPWSTR pwz_mime = nullptr;

        HRESULT hr = FindMimeFromData(nullptr,

            file_name.empty() ? nullptr : file_name.c_str(),

            mutable_buffer.data(),

            read_size,

            nullptr,

            FMFD_DEFAULT,

            &pwz_mime,

            0);




        if (SUCCEEDED(hr) && pwz_mime) {

            mime_type = pwz_mime;

            CoTaskMemFree(pwz_mime);

        }




        return mime_type;

    }




    static std::string WStringToString(const std::wstring& wstr) {

        if (wstr.empty()) return "";




        int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(),

            (int)wstr.size(), nullptr, 0, nullptr, nullptr);

        std::string str(size_needed, 0);

        WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(),

            &str[0], size_needed, nullptr, nullptr);

        return str;

    }




    static std::wstring StringToWString(const std::string& str) {

        if (str.empty()) return L"";




        int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(),

            (int)str.size(), nullptr, 0);

        std::wstring wstr(size_needed, 0);

        MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(),

            &wstr[0], size_needed);

        return wstr;

    }

};




// 创建Windows平台检测器

std::unique_ptr<IMimeTypeDetector> CreateMimeTypeDetector() {

    return std::make_unique<WindowsMimeTypeDetector>();

}




#else

// 其他平台




class DefaultMimeTypeDetector : public IMimeTypeDetector {

public:

    // 移除override关键字,使用正确的签名

    std::string GetMimeType(const std::string& file_path,

        DetectionMethod method = METHOD_BOTH) {

        return "application/octet-stream";

    }




    std::string GetMimeTypeFromMemory(const unsigned char* data,

        size_t data_size,

        const std::string& file_name = "",

        const std::string& file_ext = "") {

        return "application/octet-stream";

    }




    std::string GetFileExtension(const std::string& file_name) {

        size_t dot_pos = file_name.find_last_of('.');

        if (dot_pos != std::string::npos && dot_pos < file_name.length() - 1) {

            return file_name.substr(dot_pos + 1);

        }

        return "";

    }




    std::string GetMimeTypeFromFD(int fd,

        const std::string& file_name = "") {

        return "application/octet-stream";

    }

};




std::unique_ptr<IMimeTypeDetector> CreateMimeTypeDetector() {

    return std::make_unique<DefaultMimeTypeDetector>();

}




#endif










#include<iostream>




int main() {

    //// 初始化COM

    //CoInitialize(nullptr);




    //// 测试内存检测

    //std::vector<BYTE> pdf_data = { 0x25, 0x50, 0x44, 0x46, 0x2D };  // PDF魔术字节




    //std::wstring mime = MimeTypeDetector::GetMimeTypeFromMemory(

    //    pdf_data.data(),

    //    pdf_data.size(),

    //    L"document.pdf");




    //std::wcout << L"Detected MIME: " << mime << std::endl;




    //CoUninitialize();

    // 使用全局便捷函数

    std::string mime = GetMimeType("D:\\Users\\Pictures\\1.png");




    // 或使用工厂函数创建

    auto detector = CreateMimeTypeDetector();

    std::string mime2 = detector->GetMimeType("D:\\Users\\Pictures\\1.png");

    return 0;

}为我写一个代码的介绍大纲
相关推荐
charlee441 个月前
使用cpp-httplib发布静态文件服务
http·mime·cpp-httplib·静态文件服务
IT成长日记4 个月前
【Nginx开荒攻略】静态文件服务深度解析:MIME类型映射与优化实战
linux·运维·服务器·nginx·mime
mooyuan天天4 个月前
CTFHub 文件上传-MIME
文件上传·文件上传漏洞·mime·mime绕过
眠りたいです5 个月前
Qt音频播放器项目实践:文件过滤、元数据提取与动态歌词显示实现
c++·qt·ui·音视频·媒体·qt5·mime
SuperherRo7 个月前
Web攻防-文件上传&黑白名单&MIME&JS前端&执行权限&编码解析&OSS存储&分域名&应用场景
文件上传·mime·黑白名单·js前端·执行权限·编码解析·oss存储
mooyuan天天8 个月前
upload-labs通关笔记-第2关 文件上传之MIME绕过
web安全·文件上传·文件上传漏洞·mime·upload-labs靶场
蜗牛、Z2 年前
okHttp MediaType MIME格式详解
android·java·okhttp·mime
狂龙骄子2 年前
JSON的MIME媒体类型是application/json
application·mime·json媒体类型·applicationjson·rfc 4627