|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
namespace System.Net.Mime
{
/// <summary>
/// Provides methods for mapping between file extensions and media types (MIME types).
/// </summary>
public static class MediaTypeMap
{
private const int ExtensionToMediaTypeCount = 403;
private const int MediaTypeToExtensionCount = 294;
private const int MaxExtensionLength = 12; // Length of longest extension including the dot
private static readonly Dictionary<string, string>.AlternateLookup<ReadOnlySpan<char>> s_extensionToMediaType = new Dictionary<string, string>(ExtensionToMediaTypeCount, StringComparer.OrdinalIgnoreCase)
{
[".3g2"] = "video/3gpp2",
[".3gp"] = "video/3gpp",
[".3gp2"] = "video/3gpp2",
[".3gpp"] = "video/3gpp",
[".7z"] = "application/x-7z-compressed",
[".aac"] = "audio/aac",
[".abw"] = "application/x-abiword",
[".accdb"] = "application/msaccess",
[".accde"] = "application/msaccess",
[".accdt"] = "application/msaccess",
[".adt"] = "audio/vnd.dlna.adts",
[".adts"] = "audio/vnd.dlna.adts",
[".ai"] = "application/postscript",
[".aif"] = "audio/x-aiff",
[".aifc"] = "audio/aifc",
[".aiff"] = "audio/aiff",
[".apk"] = "application/vnd.android.package-archive",
[".apng"] = "image/apng",
[".appcache"] = "text/cache-manifest",
[".application"] = "application/x-ms-application",
[".arc"] = "application/x-freearc",
[".asf"] = "video/x-ms-asf",
[".asm"] = "text/plain",
[".asr"] = "video/x-ms-asf",
[".asx"] = "video/x-ms-asf",
[".atom"] = "application/atom+xml",
[".au"] = "audio/basic",
[".avi"] = "video/x-msvideo",
[".avif"] = "image/avif",
[".azw"] = "application/vnd.amazon.ebook",
[".bas"] = "text/plain",
[".bcpio"] = "application/x-bcpio",
[".bmp"] = "image/bmp",
[".br"] = "application/brotli",
[".bz"] = "application/x-bzip",
[".bz2"] = "application/x-bzip2",
[".c"] = "text/plain",
[".cab"] = "application/vnd.ms-cab-compressed",
[".calx"] = "application/vnd.ms-office.calx",
[".cat"] = "application/vnd.ms-pki.seccat",
[".cbor"] = "application/cbor",
[".cdf"] = "application/x-cdf",
[".cer"] = "application/x-x509-ca-cert",
[".cjs"] = "text/javascript",
[".class"] = "application/java-vm",
[".clp"] = "application/x-msclip",
[".cmx"] = "image/x-cmx",
[".cnf"] = "text/plain",
[".config"] = "text/plain",
[".cpio"] = "application/x-cpio",
[".cpp"] = "text/plain",
[".crd"] = "application/x-mscardfile",
[".crl"] = "application/pkix-crl",
[".crt"] = "application/x-x509-ca-cert",
[".cs"] = "text/x-csharp",
[".csproj"] = "text/xml",
[".csh"] = "application/x-csh",
[".css"] = "text/css",
[".csv"] = "text/csv",
[".cue"] = "application/x-cue",
[".cts"] = "text/typescript",
[".dart"] = "text/x-dart",
[".db"] = "application/x-sqlite3",
[".dbf"] = "application/x-dbf",
[".deb"] = "application/vnd.debian.binary-package",
[".dcr"] = "application/x-director",
[".der"] = "application/x-x509-ca-cert",
[".dib"] = "image/bmp",
[".dir"] = "application/x-director",
[".disco"] = "text/xml",
[".dmg"] = "application/x-apple-diskimage",
[".doc"] = "application/msword",
[".docm"] = "application/vnd.ms-word.document.macroEnabled.12",
[".docx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
[".dot"] = "application/msword",
[".dotm"] = "application/vnd.ms-word.template.macroEnabled.12",
[".dotx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
[".dtd"] = "application/xml-dtd",
[".dvi"] = "application/x-dvi",
[".dvr-ms"] = "video/x-ms-dvr",
[".dwf"] = "drawing/x-dwf",
[".dxr"] = "application/x-director",
[".eml"] = "message/rfc822",
[".eot"] = "application/vnd.ms-fontobject",
[".eps"] = "application/postscript",
[".epub"] = "application/epub+zip",
[".etx"] = "text/x-setext",
[".fdf"] = "application/vnd.fdf",
[".flac"] = "audio/flac",
[".flv"] = "video/x-flv",
[".geojson"] = "application/geo+json",
[".gif"] = "image/gif",
[".glb"] = "model/gltf-binary",
[".gltf"] = "model/gltf+json",
[".go"] = "text/x-go",
[".gpx"] = "application/gpx+xml",
[".graphql"] = "application/graphql",
[".gtar"] = "application/x-gtar",
[".gz"] = "application/gzip",
[".h"] = "text/plain",
[".hdf"] = "application/x-hdf",
[".heic"] = "image/heic",
[".heif"] = "image/heif",
[".hhc"] = "application/x-oleobject",
[".hlp"] = "application/winhlp",
[".hqx"] = "application/mac-binhex40",
[".hta"] = "application/hta",
[".htc"] = "text/x-component",
[".htm"] = "text/html",
[".html"] = "text/html",
[".hwp"] = "application/x-hwp",
[".ical"] = "text/calendar",
[".icalendar"] = "text/calendar",
[".ico"] = "image/vnd.microsoft.icon",
[".ics"] = "text/calendar",
[".ief"] = "image/ief",
[".ifb"] = "text/calendar",
[".ini"] = "text/plain",
[".ins"] = "application/x-internet-signup",
[".iso"] = "application/x-iso9660-image",
[".isp"] = "application/x-internet-signup",
[".ivf"] = "video/x-ivf",
[".jar"] = "application/java-archive",
[".java"] = "text/x-java-source",
[".jfif"] = "image/jpeg",
[".jpe"] = "image/jpeg",
[".jpeg"] = "image/jpeg",
[".jpg"] = "image/jpeg",
[".js"] = "text/javascript",
[".json"] = "application/json",
[".jsonld"] = "application/ld+json",
[".jsonl"] = "application/x-ndjson",
[".jsx"] = "text/jsx",
[".jxl"] = "image/jxl",
[".kt"] = "text/x-kotlin",
[".kts"] = "text/x-kotlin",
[".key"] = "application/vnd.apple.keynote",
[".kml"] = "application/vnd.google-earth.kml+xml",
[".kmz"] = "application/vnd.google-earth.kmz",
[".latex"] = "application/x-latex",
[".less"] = "text/x-less",
[".lit"] = "application/x-ms-reader",
[".log"] = "text/plain",
[".lsf"] = "video/x-la-asf",
[".lwp"] = "application/vnd.lotus-wordpro",
[".lsx"] = "video/x-la-asf",
[".m13"] = "application/x-msmediaview",
[".m14"] = "application/x-msmediaview",
[".m1v"] = "video/mpeg",
[".m2t"] = "video/vnd.dlna.mpeg-tts",
[".m2ts"] = "video/vnd.dlna.mpeg-tts",
[".m3u"] = "audio/x-mpegurl",
[".m3u8"] = "application/vnd.apple.mpegurl",
[".m4a"] = "audio/mp4",
[".m4v"] = "video/mp4",
[".man"] = "application/x-troff-man",
[".manifest"] = "application/x-ms-manifest",
[".markdown"] = "text/markdown",
[".md"] = "text/markdown",
[".mdb"] = "application/x-msaccess",
[".mdx"] = "text/mdx",
[".me"] = "application/x-troff-me",
[".mht"] = "message/rfc822",
[".mhtml"] = "message/rfc822",
[".mid"] = "audio/midi",
[".midi"] = "audio/midi",
[".mjs"] = "text/javascript",
[".mka"] = "audio/x-matroska",
[".mkv"] = "video/x-matroska",
[".mmf"] = "application/x-smaf",
[".mno"] = "text/xml",
[".mny"] = "application/x-msmoney",
[".mov"] = "video/quicktime",
[".movie"] = "video/x-sgi-movie",
[".mp2"] = "video/mpeg",
[".mp3"] = "audio/mpeg",
[".mp4"] = "video/mp4",
[".mp4v"] = "video/mp4",
[".mpa"] = "video/mpeg",
[".mpd"] = "application/dash+xml",
[".mpe"] = "video/mpeg",
[".mpeg"] = "video/mpeg",
[".mpg"] = "video/mpeg",
[".mpkg"] = "application/vnd.apple.installer+xml",
[".mpp"] = "application/vnd.ms-project",
[".mpv2"] = "video/mpeg",
[".mts"] = "video/mp2t",
[".mvb"] = "application/x-msmediaview",
[".mvc"] = "application/x-miva-compiled",
[".nc"] = "application/x-netcdf",
[".nsc"] = "video/x-ms-asf",
[".ndjson"] = "application/x-ndjson",
[".numbers"] = "application/vnd.apple.numbers",
[".nupkg"] = "application/zip",
[".nws"] = "message/rfc822",
[".oda"] = "application/oda",
[".odc"] = "text/x-ms-odc",
[".odf"] = "application/vnd.oasis.opendocument.formula",
[".odg"] = "application/vnd.oasis.opendocument.graphics",
[".odp"] = "application/vnd.oasis.opendocument.presentation",
[".ods"] = "application/vnd.oasis.opendocument.spreadsheet",
[".odt"] = "application/vnd.oasis.opendocument.text",
[".oga"] = "audio/ogg",
[".ogg"] = "audio/ogg",
[".ogv"] = "video/ogg",
[".ogx"] = "application/ogg",
[".one"] = "application/onenote",
[".onea"] = "application/onenote",
[".onepkg"] = "application/onenote",
[".onetmp"] = "application/onenote",
[".onetoc"] = "application/onenote",
[".onetoc2"] = "application/onenote",
[".opus"] = "audio/opus",
[".osdx"] = "application/opensearchdescription+xml",
[".otf"] = "font/otf",
[".pages"] = "application/vnd.apple.pages",
[".parquet"] = "application/vnd.apache.parquet",
[".p10"] = "application/pkcs10",
[".p12"] = "application/x-pkcs12",
[".p7b"] = "application/x-pkcs7-certificates",
[".p7c"] = "application/pkcs7-mime",
[".p7m"] = "application/pkcs7-mime",
[".p7r"] = "application/x-pkcs7-certreqresp",
[".p7s"] = "application/pkcs7-signature",
[".pbm"] = "image/x-portable-bitmap",
[".pdf"] = "application/pdf",
[".pem"] = "application/x-pem-file",
[".pfx"] = "application/x-pkcs12",
[".pgm"] = "image/x-portable-graymap",
[".php"] = "application/x-httpd-php",
[".pko"] = "application/vnd.ms-pki.pko",
[".pl"] = "text/x-perl",
[".pm"] = "text/x-perl",
[".pma"] = "application/x-perfmon",
[".pmc"] = "application/x-perfmon",
[".pml"] = "application/x-perfmon",
[".pmr"] = "application/x-perfmon",
[".pmw"] = "application/x-perfmon",
[".png"] = "image/png",
[".pnm"] = "image/x-portable-anymap",
[".pnz"] = "image/png",
[".pot"] = "application/vnd.ms-powerpoint",
[".potm"] = "application/vnd.ms-powerpoint.template.macroEnabled.12",
[".potx"] = "application/vnd.openxmlformats-officedocument.presentationml.template",
[".ppam"] = "application/vnd.ms-powerpoint.addin.macroEnabled.12",
[".ppm"] = "image/x-portable-pixmap",
[".pps"] = "application/vnd.ms-powerpoint",
[".ppsm"] = "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
[".ppsx"] = "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
[".ppt"] = "application/vnd.ms-powerpoint",
[".pptm"] = "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
[".pptx"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation",
[".proto"] = "text/x-protobuf",
[".ps"] = "application/postscript",
[".ps1"] = "application/powershell",
[".pub"] = "application/x-mspublisher",
[".py"] = "text/x-python",
[".pyi"] = "text/x-python",
[".pyw"] = "text/x-python",
[".qt"] = "video/quicktime",
[".qtl"] = "application/x-quicktimeplayer",
[".rar"] = "application/vnd.rar",
[".ras"] = "image/x-cmu-raster",
[".rgb"] = "image/x-rgb",
[".rmi"] = "audio/mid",
[".roff"] = "application/x-troff",
[".rpm"] = "application/x-rpm",
[".rs"] = "text/x-rust",
[".rss"] = "application/rss+xml",
[".rtf"] = "application/rtf",
[".rtx"] = "text/richtext",
[".sass"] = "text/x-sass",
[".scd"] = "application/x-msschedule",
[".scss"] = "text/x-scss",
[".sct"] = "text/scriptlet",
[".sda"] = "application/vnd.stardivision.draw",
[".sdd"] = "application/vnd.stardivision.impress",
[".sdw"] = "application/vnd.stardivision.writer",
[".setpay"] = "application/set-payment-initiation",
[".setreg"] = "application/set-registration-initiation",
[".sgml"] = "text/sgml",
[".sh"] = "application/x-sh",
[".shar"] = "application/x-shar",
[".sit"] = "application/x-stuffit",
[".slk"] = "text/vnd.sylk",
[".sln"] = "text/plain",
[".sldm"] = "application/vnd.ms-powerpoint.slide.macroEnabled.12",
[".sldx"] = "application/vnd.openxmlformats-officedocument.presentationml.slide",
[".snd"] = "audio/basic",
[".snupkg"] = "application/zip",
[".spc"] = "application/x-pkcs7-certificates",
[".spx"] = "audio/ogg",
[".sql"] = "application/sql",
[".sqlite"] = "application/x-sqlite3",
[".sqlite3"] = "application/x-sqlite3",
[".src"] = "application/x-wais-source",
[".sst"] = "application/vnd.ms-pki.certstore",
[".sti"] = "application/vnd.sun.xml.impress.template",
[".stl"] = "model/stl",
[".stw"] = "application/vnd.sun.xml.writer.template",
[".sv4cpio"] = "application/x-sv4cpio",
[".sv4crc"] = "application/x-sv4crc",
[".svelte"] = "text/svelte",
[".svg"] = "image/svg+xml",
[".svgz"] = "image/svg+xml",
[".sxg"] = "application/vnd.sun.xml.writer.global",
[".sxi"] = "application/vnd.sun.xml.impress",
[".sxw"] = "application/vnd.sun.xml.writer",
[".swf"] = "application/x-shockwave-flash",
[".sylk"] = "text/vnd.sylk",
[".swift"] = "text/x-swift",
[".tar"] = "application/x-tar",
[".tcl"] = "application/x-tcl",
[".tex"] = "application/x-tex",
[".texi"] = "application/x-texinfo",
[".texinfo"] = "application/x-texinfo",
[".tgz"] = "application/x-compressed",
[".thmx"] = "application/vnd.ms-officetheme",
[".tif"] = "image/tiff",
[".tiff"] = "image/tiff",
[".toml"] = "application/toml",
[".tr"] = "application/x-troff",
[".trm"] = "application/x-msterminal",
[".ts"] = "text/typescript",
[".tsv"] = "text/tab-separated-values",
[".tsx"] = "text/tsx",
[".ttc"] = "font/collection",
[".ttf"] = "font/ttf",
[".tts"] = "video/vnd.dlna.mpeg-tts",
[".txt"] = "text/plain",
[".ustar"] = "application/x-ustar",
[".vbs"] = "text/vbscript",
[".vcf"] = "text/vcard",
[".vcs"] = "text/x-vcalendar",
[".vdx"] = "application/vnd.ms-visio.viewer",
[".vml"] = "text/xml",
[".vsd"] = "application/vnd.visio",
[".vss"] = "application/vnd.visio",
[".vst"] = "application/vnd.visio",
[".vsto"] = "application/x-ms-vsto",
[".vsw"] = "application/vnd.visio",
[".vsx"] = "application/vnd.visio",
[".vtt"] = "text/vtt",
[".vtx"] = "application/vnd.visio",
[".vue"] = "text/vue",
[".wasm"] = "application/wasm",
[".wav"] = "audio/wav",
[".wax"] = "audio/x-ms-wax",
[".wbmp"] = "image/vnd.wap.wbmp",
[".wcm"] = "application/vnd.ms-works",
[".wdb"] = "application/vnd.ms-works",
[".weba"] = "audio/webm",
[".webm"] = "video/webm",
[".webmanifest"] = "application/manifest+json",
[".webp"] = "image/webp",
[".wks"] = "application/vnd.ms-works",
[".wm"] = "video/x-ms-wm",
[".wma"] = "audio/x-ms-wma",
[".wmd"] = "application/x-ms-wmd",
[".wmf"] = "application/x-msmetafile",
[".wmp"] = "video/x-ms-wmp",
[".wmv"] = "video/x-ms-wmv",
[".wmx"] = "video/x-ms-wmx",
[".wmz"] = "application/x-ms-wmz",
[".woff"] = "font/woff",
[".woff2"] = "font/woff2",
[".wpd"] = "application/vnd.wordperfect",
[".wps"] = "application/vnd.ms-works",
[".wri"] = "application/x-mswrite",
[".wsdl"] = "text/xml",
[".wtv"] = "video/x-ms-wtv",
[".wvx"] = "video/x-ms-wvx",
[".xaml"] = "application/xaml+xml",
[".xbm"] = "image/x-xbitmap",
[".xdr"] = "text/plain",
[".xht"] = "application/xhtml+xml",
[".xhtml"] = "application/xhtml+xml",
[".xla"] = "application/vnd.ms-excel",
[".xlam"] = "application/vnd.ms-excel.addin.macroEnabled.12",
[".xlc"] = "application/vnd.ms-excel",
[".xlm"] = "application/vnd.ms-excel",
[".xls"] = "application/vnd.ms-excel",
[".xlsb"] = "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
[".xlsm"] = "application/vnd.ms-excel.sheet.macroEnabled.12",
[".xlsx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
[".xlt"] = "application/vnd.ms-excel",
[".xltm"] = "application/vnd.ms-excel.template.macroEnabled.12",
[".xltx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
[".xlw"] = "application/vnd.ms-excel",
[".xml"] = "application/xml",
[".xpm"] = "image/x-xpixmap",
[".xps"] = "application/vnd.ms-xpsdocument",
[".xsd"] = "text/xml",
[".xsf"] = "text/xml",
[".xsl"] = "text/xml",
[".xslt"] = "text/xml",
[".xul"] = "application/vnd.mozilla.xul+xml",
[".xwd"] = "image/x-xwindowdump",
[".yaml"] = "application/yaml",
[".yml"] = "application/yaml",
[".z"] = "application/x-compress",
[".zip"] = "application/zip",
[".zst"] = "application/zstd",
}.GetAlternateLookup<ReadOnlySpan<char>>();
private static readonly Dictionary<string, string>.AlternateLookup<ReadOnlySpan<char>> s_mediaTypeToExtension = new Dictionary<string, string>(MediaTypeToExtensionCount, StringComparer.OrdinalIgnoreCase)
{
["application/atom+xml"] = ".atom",
["application/brotli"] = ".br",
["application/cbor"] = ".cbor",
["application/dash+xml"] = ".mpd",
["application/epub+zip"] = ".epub",
["application/geo+json"] = ".geojson",
["application/graphql"] = ".graphql",
["application/gpx+xml"] = ".gpx",
["application/gzip"] = ".gz",
["application/hta"] = ".hta",
["application/java-archive"] = ".jar",
["application/java-vm"] = ".class",
["application/json"] = ".json",
["application/ld+json"] = ".jsonld",
["application/mac-binhex40"] = ".hqx",
["application/manifest+json"] = ".webmanifest",
["application/msaccess"] = ".mdb",
["application/msword"] = ".doc",
["application/oda"] = ".oda",
["application/ogg"] = ".ogx",
["application/onenote"] = ".one",
["application/opensearchdescription+xml"] = ".osdx",
["application/pdf"] = ".pdf",
["application/pkcs10"] = ".p10",
["application/pkcs7-mime"] = ".p7c",
["application/pkcs7-signature"] = ".p7s",
["application/pkix-crl"] = ".crl",
["application/powershell"] = ".ps1",
["application/postscript"] = ".ps",
["application/rtf"] = ".rtf",
["application/rss+xml"] = ".rss",
["application/set-payment-initiation"] = ".setpay",
["application/set-registration-initiation"] = ".setreg",
["application/sql"] = ".sql",
["application/toml"] = ".toml",
["application/vnd.amazon.ebook"] = ".azw",
["application/vnd.android.package-archive"] = ".apk",
["application/vnd.apache.parquet"] = ".parquet",
["application/vnd.apple.installer+xml"] = ".mpkg",
["application/vnd.apple.keynote"] = ".key",
["application/vnd.apple.mpegurl"] = ".m3u8",
["application/vnd.apple.numbers"] = ".numbers",
["application/vnd.apple.pages"] = ".pages",
["application/vnd.debian.binary-package"] = ".deb",
["application/vnd.fdf"] = ".fdf",
["application/vnd.google-earth.kml+xml"] = ".kml",
["application/vnd.google-earth.kmz"] = ".kmz",
["application/vnd.lotus-wordpro"] = ".lwp",
["application/vnd.mozilla.xul+xml"] = ".xul",
["application/vnd.ms-cab-compressed"] = ".cab",
["application/vnd.ms-excel"] = ".xls",
["application/vnd.ms-excel.addin.macroEnabled.12"] = ".xlam",
["application/vnd.ms-excel.sheet.binary.macroEnabled.12"] = ".xlsb",
["application/vnd.ms-excel.sheet.macroEnabled.12"] = ".xlsm",
["application/vnd.ms-excel.template.macroEnabled.12"] = ".xltm",
["application/vnd.ms-fontobject"] = ".eot",
["application/vnd.ms-office.calx"] = ".calx",
["application/vnd.ms-officetheme"] = ".thmx",
["application/vnd.ms-pki.certstore"] = ".sst",
["application/vnd.ms-pki.pko"] = ".pko",
["application/vnd.ms-pki.seccat"] = ".cat",
["application/vnd.ms-powerpoint"] = ".ppt",
["application/vnd.ms-powerpoint.addin.macroEnabled.12"] = ".ppam",
["application/vnd.ms-powerpoint.presentation.macroEnabled.12"] = ".pptm",
["application/vnd.ms-powerpoint.slide.macroEnabled.12"] = ".sldm",
["application/vnd.ms-powerpoint.slideshow.macroEnabled.12"] = ".ppsm",
["application/vnd.ms-powerpoint.template.macroEnabled.12"] = ".potm",
["application/vnd.ms-project"] = ".mpp",
["application/vnd.ms-visio.viewer"] = ".vdx",
["application/vnd.ms-word.document.macroEnabled.12"] = ".docm",
["application/vnd.ms-word.template.macroEnabled.12"] = ".dotm",
["application/vnd.ms-works"] = ".wcm",
["application/vnd.ms-xpsdocument"] = ".xps",
["application/vnd.oasis.opendocument.formula"] = ".odf",
["application/vnd.oasis.opendocument.graphics"] = ".odg",
["application/vnd.oasis.opendocument.presentation"] = ".odp",
["application/vnd.oasis.opendocument.spreadsheet"] = ".ods",
["application/vnd.oasis.opendocument.text"] = ".odt",
["application/vnd.openxmlformats-officedocument.presentationml.presentation"] = ".pptx",
["application/vnd.openxmlformats-officedocument.presentationml.slide"] = ".sldx",
["application/vnd.openxmlformats-officedocument.presentationml.slideshow"] = ".ppsx",
["application/vnd.openxmlformats-officedocument.presentationml.template"] = ".potx",
["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = ".xlsx",
["application/vnd.openxmlformats-officedocument.spreadsheetml.template"] = ".xltx",
["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] = ".docx",
["application/vnd.openxmlformats-officedocument.wordprocessingml.template"] = ".dotx",
["application/vnd.rar"] = ".rar",
["application/vnd.stardivision.draw"] = ".sda",
["application/vnd.stardivision.impress"] = ".sdd",
["application/vnd.stardivision.writer"] = ".sdw",
["application/vnd.sun.xml.impress"] = ".sxi",
["application/vnd.sun.xml.impress.template"] = ".sti",
["application/vnd.sun.xml.writer"] = ".sxw",
["application/vnd.sun.xml.writer.global"] = ".sxg",
["application/vnd.sun.xml.writer.template"] = ".stw",
["application/vnd.visio"] = ".vsd",
["application/vnd.wordperfect"] = ".wpd",
["application/wasm"] = ".wasm",
["application/winhlp"] = ".hlp",
["application/x-7z-compressed"] = ".7z",
["application/x-abiword"] = ".abw",
["application/x-apple-diskimage"] = ".dmg",
["application/xaml+xml"] = ".xaml",
["application/x-bcpio"] = ".bcpio",
["application/x-dbf"] = ".dbf",
["application/x-brotli"] = ".br",
["application/x-bzip"] = ".bz",
["application/x-bzip2"] = ".bz2",
["application/x-cdf"] = ".cdf",
["application/x-compress"] = ".z",
["application/x-compressed"] = ".tgz",
["application/x-cpio"] = ".cpio",
["application/x-cue"] = ".cue",
["application/x-csh"] = ".csh",
["application/x-director"] = ".dcr",
["application/x-dvi"] = ".dvi",
["application/x-freearc"] = ".arc",
["application/x-gtar"] = ".gtar",
["application/x-hdf"] = ".hdf",
["application/x-hwp"] = ".hwp",
["application/x-iso9660-image"] = ".iso",
["application/xhtml+xml"] = ".xhtml",
["application/x-httpd-php"] = ".php",
["application/x-internet-signup"] = ".ins",
["application/x-latex"] = ".latex",
["application/x-miva-compiled"] = ".mvc",
["application/xml"] = ".xml",
["application/xml-dtd"] = ".dtd",
["application/x-msaccess"] = ".mdb",
["application/x-ms-application"] = ".application",
["application/x-mscardfile"] = ".crd",
["application/x-msclip"] = ".clp",
["application/x-ms-manifest"] = ".manifest",
["application/x-msmediaview"] = ".m13",
["application/x-msmetafile"] = ".wmf",
["application/x-msmoney"] = ".mny",
["application/x-mspublisher"] = ".pub",
["application/x-ms-reader"] = ".lit",
["application/x-msschedule"] = ".scd",
["application/x-msterminal"] = ".trm",
["application/x-ms-vsto"] = ".vsto",
["application/x-ms-wmd"] = ".wmd",
["application/x-ms-wmz"] = ".wmz",
["application/x-mswrite"] = ".wri",
["application/x-netcdf"] = ".nc",
["application/x-ndjson"] = ".jsonl",
["application/x-oleobject"] = ".hhc",
["application/x-perfmon"] = ".pma",
["application/x-pem-file"] = ".pem",
["application/x-pkcs12"] = ".p12",
["application/x-pkcs7-certificates"] = ".p7b",
["application/x-pkcs7-certreqresp"] = ".p7r",
["application/x-quicktimeplayer"] = ".qtl",
["application/x-rpm"] = ".rpm",
["application/x-sh"] = ".sh",
["application/x-shar"] = ".shar",
["application/x-shockwave-flash"] = ".swf",
["application/x-smaf"] = ".mmf",
["application/x-sqlite3"] = ".sqlite",
["application/x-stuffit"] = ".sit",
["application/x-sv4cpio"] = ".sv4cpio",
["application/x-sv4crc"] = ".sv4crc",
["application/x-tar"] = ".tar",
["application/x-tcl"] = ".tcl",
["application/x-tex"] = ".tex",
["application/x-texinfo"] = ".texi",
["application/x-troff"] = ".roff",
["application/x-troff-man"] = ".man",
["application/x-troff-me"] = ".me",
["application/x-ustar"] = ".ustar",
["application/x-wais-source"] = ".src",
["application/x-x509-ca-cert"] = ".crt",
["application/yaml"] = ".yaml",
["application/zip"] = ".zip",
["application/zstd"] = ".zst",
["audio/aac"] = ".aac",
["audio/aifc"] = ".aifc",
["audio/aiff"] = ".aiff",
["audio/basic"] = ".au",
["audio/flac"] = ".flac",
["audio/mid"] = ".mid",
["audio/midi"] = ".mid",
["audio/mp4"] = ".m4a",
["audio/mpeg"] = ".mp3",
["audio/ogg"] = ".oga",
["audio/opus"] = ".opus",
["audio/vnd.dlna.adts"] = ".adt",
["audio/wav"] = ".wav",
["audio/webm"] = ".weba",
["audio/x-aiff"] = ".aif",
["audio/x-mpegurl"] = ".m3u",
["audio/x-matroska"] = ".mka",
["audio/x-ms-wax"] = ".wax",
["audio/x-ms-wma"] = ".wma",
["drawing/x-dwf"] = ".dwf",
["font/collection"] = ".ttc",
["font/otf"] = ".otf",
["font/ttf"] = ".ttf",
["font/woff"] = ".woff",
["font/woff2"] = ".woff2",
["image/apng"] = ".apng",
["image/avif"] = ".avif",
["image/bmp"] = ".bmp",
["image/gif"] = ".gif",
["image/heic"] = ".heic",
["image/heif"] = ".heif",
["image/ief"] = ".ief",
["image/jpeg"] = ".jpg",
["image/jxl"] = ".jxl",
["image/png"] = ".png",
["image/svg+xml"] = ".svg",
["image/tiff"] = ".tif",
["image/vnd.microsoft.icon"] = ".ico",
["image/vnd.wap.wbmp"] = ".wbmp",
["image/webp"] = ".webp",
["image/x-cmu-raster"] = ".ras",
["image/x-cmx"] = ".cmx",
["image/x-icon"] = ".ico",
["image/x-portable-anymap"] = ".pnm",
["image/x-portable-bitmap"] = ".pbm",
["image/x-portable-graymap"] = ".pgm",
["image/x-portable-pixmap"] = ".ppm",
["image/x-rgb"] = ".rgb",
["image/x-xbitmap"] = ".xbm",
["image/x-xpixmap"] = ".xpm",
["image/x-xwindowdump"] = ".xwd",
["message/rfc822"] = ".eml",
["model/gltf+json"] = ".gltf",
["model/gltf-binary"] = ".glb",
["model/stl"] = ".stl",
["text/cache-manifest"] = ".appcache",
["text/calendar"] = ".ics",
["text/css"] = ".css",
["text/csv"] = ".csv",
["text/html"] = ".html",
["text/javascript"] = ".js",
["text/jsx"] = ".jsx",
["text/markdown"] = ".md",
["text/mdx"] = ".mdx",
["text/plain"] = ".txt",
["text/richtext"] = ".rtx",
["text/scriptlet"] = ".sct",
["text/sgml"] = ".sgml",
["text/svelte"] = ".svelte",
["text/tab-separated-values"] = ".tsv",
["text/tsx"] = ".tsx",
["text/typescript"] = ".ts",
["text/vbscript"] = ".vbs",
["text/vcard"] = ".vcf",
["text/vnd.sylk"] = ".sylk",
["text/vtt"] = ".vtt",
["text/x-vcalendar"] = ".vcs",
["text/vue"] = ".vue",
["text/x-component"] = ".htc",
["text/x-csharp"] = ".cs",
["text/x-dart"] = ".dart",
["text/x-go"] = ".go",
["text/x-java-source"] = ".java",
["text/x-kotlin"] = ".kt",
["text/x-less"] = ".less",
["text/xml"] = ".xml",
["text/x-ms-odc"] = ".odc",
["text/yaml"] = ".yaml",
["text/x-perl"] = ".pl",
["text/x-protobuf"] = ".proto",
["text/x-python"] = ".py",
["text/x-rust"] = ".rs",
["text/x-sass"] = ".sass",
["text/x-scss"] = ".scss",
["text/x-setext"] = ".etx",
["text/x-swift"] = ".swift",
["video/3gpp"] = ".3gp",
["video/3gpp2"] = ".3g2",
["video/mp2t"] = ".mts",
["video/mp4"] = ".mp4",
["video/mpeg"] = ".mpeg",
["video/ogg"] = ".ogv",
["video/quicktime"] = ".mov",
["video/vnd.dlna.mpeg-tts"] = ".tts",
["video/webm"] = ".webm",
["video/x-flv"] = ".flv",
["video/x-ivf"] = ".ivf",
["video/x-la-asf"] = ".lsf",
["video/x-matroska"] = ".mkv",
["video/x-ms-asf"] = ".asf",
["video/x-ms-dvr"] = ".dvr-ms",
["video/x-msvideo"] = ".avi",
["video/x-ms-wm"] = ".wm",
["video/x-ms-wmp"] = ".wmp",
["video/x-ms-wmv"] = ".wmv",
["video/x-ms-wmx"] = ".wmx",
["video/x-ms-wtv"] = ".wtv",
["video/x-ms-wvx"] = ".wvx",
["video/x-sgi-movie"] = ".movie",
}.GetAlternateLookup<ReadOnlySpan<char>>();
#if DEBUG
static MediaTypeMap()
{
// Validate dictionary consistency.
int longestExtensionLength = 0;
Debug.Assert(ExtensionToMediaTypeCount == s_extensionToMediaType.Dictionary.Count,
$"Expected {ExtensionToMediaTypeCount} entries in {nameof(s_extensionToMediaType)}, but found {s_extensionToMediaType.Dictionary.Count}.");
foreach (KeyValuePair<string, string> entry in s_extensionToMediaType.Dictionary)
{
Debug.Assert(
s_mediaTypeToExtension.ContainsKey(entry.Value),
$"Missing '{entry.Value}' in {nameof(s_mediaTypeToExtension)}");
longestExtensionLength = Math.Max(longestExtensionLength, entry.Key.Length);
}
Debug.Assert(MediaTypeToExtensionCount == s_mediaTypeToExtension.Dictionary.Count,
$"Expected {MediaTypeToExtensionCount} entries in {nameof(s_mediaTypeToExtension)}, but found {s_mediaTypeToExtension.Dictionary.Count}.");
foreach (KeyValuePair<string, string> entry in s_mediaTypeToExtension.Dictionary)
{
Debug.Assert(
s_extensionToMediaType.ContainsKey(entry.Value),
$"Missing '{entry.Value}' in {nameof(s_extensionToMediaType)}");
longestExtensionLength = Math.Max(longestExtensionLength, entry.Value.Length);
}
Debug.Assert(longestExtensionLength == MaxExtensionLength,
$"Expected {MaxExtensionLength} as longest extension length, but found {longestExtensionLength}.");
}
#endif
/// <summary>
/// Gets the media type (MIME type) for the specified file path or extension.
/// </summary>
/// <param name="pathOrExtension">A file path or extension (with or without leading period).</param>
/// <returns>The media type associated with the extension, or <see langword="null"/> if no mapping exists.</returns>
/// <remarks>
/// <para>
/// Some file extensions may map to multiple media types. In such cases, this method returns one of the possible media types.
/// </para>
/// <para>
/// The method extracts the extension from <paramref name="pathOrExtension"/> using the same logic as <see cref="Path.GetExtension(string)"/>.
/// If the input is already an extension (e.g. ".pdf" or "pdf"), it will be used directly.
/// The comparison is case-insensitive.
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="pathOrExtension"/> is <see langword="null"/>.</exception>
public static string? GetMediaType(string pathOrExtension)
{
ArgumentNullException.ThrowIfNull(pathOrExtension);
return GetMediaType(pathOrExtension.AsSpan());
}
/// <summary>
/// Gets the media type (MIME type) for the specified file path or extension.
/// </summary>
/// <param name="pathOrExtension">A file path or extension (with or without leading period).</param>
/// <returns>The media type associated with the extension, or <see langword="null"/> if no mapping exists.</returns>
/// <remarks>
/// <para>
/// Some file extensions may map to multiple media types. In such cases, this method returns one of the possible media types.
/// </para>
/// <para>
/// The method extracts the extension from <paramref name="pathOrExtension"/> using the same logic as <see cref="Path.GetExtension(ReadOnlySpan{char})"/>.
/// If the input is already an extension (e.g. ".pdf" or "pdf"), it will be used directly.
/// The comparison is case-insensitive.
/// </para>
/// </remarks>
public static string? GetMediaType(ReadOnlySpan<char> pathOrExtension)
{
scoped ReadOnlySpan<char> extension = Path.GetExtension(pathOrExtension);
if (extension.IsEmpty)
{
// We couldn't extract an extension, so try using the full input.
// If it doesn't start with a period, add one. If it's too long, just use as-is,
// as it'll fail the lookup anyway.
extension = pathOrExtension;
if (!extension.IsEmpty && extension[0] != '.' && extension.Length < MaxExtensionLength)
{
Span<char> buffer = stackalloc char[1 + extension.Length];
buffer.TryWrite($".{extension}", out _);
extension = buffer;
}
}
s_extensionToMediaType.TryGetValue(extension, out string? result);
return result;
}
/// <summary>
/// Gets the file extension for the specified media type (MIME type).
/// </summary>
/// <param name="mediaType">The media type (e.g. "application/pdf").</param>
/// <returns>The file extension (with leading period) associated with the media type, or <see langword="null"/> if no mapping exists.</returns>
/// <remarks>
/// <para>
/// Some media types may map to multiple file extensions. In such cases, this method returns one of the possible file extensions.
/// </para>
/// <para>
/// The comparison is case-insensitive. Parameters in the media type (e.g. "text/html; charset=utf-8") are ignored.
/// </para>
/// </remarks>
/// <exception cref="ArgumentNullException"><paramref name="mediaType"/> is <see langword="null"/>.</exception>
public static string? GetExtension(string mediaType)
{
ArgumentNullException.ThrowIfNull(mediaType);
return GetExtension(mediaType.AsSpan());
}
/// <summary>
/// Gets the file extension for the specified media type (MIME type).
/// </summary>
/// <param name="mediaType">The media type (e.g. "application/pdf").</param>
/// <returns>The file extension (with leading period) associated with the media type, or <see langword="null"/> if no mapping exists.</returns>
/// <remarks>
/// <para>
/// Some media types may map to multiple file extensions. In such cases, this method returns one of the possible file extensions.
/// </para>
/// <para>
/// The comparison is case-insensitive. Parameters in the media type (e.g. "text/html; charset=utf-8") are ignored.
/// </para>
/// </remarks>
public static string? GetExtension(ReadOnlySpan<char> mediaType)
{
int pos = mediaType.IndexOf(';');
if (pos >= 0)
{
mediaType = mediaType.Slice(0, pos);
}
s_mediaTypeToExtension.TryGetValue(mediaType.Trim(), out string? value);
return value;
}
}
}
|