using System; using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Model.Extensions; namespace MediaBrowser.Model.Net { /// /// Class MimeTypes /// public static class MimeTypes { /// /// Any extension in this list is considered a video file - can be added to at runtime for extensibility /// private static readonly string[] VideoFileExtensions = new string[] { ".mkv", ".m2t", ".m2ts", ".img", ".iso", ".mk3d", ".ts", ".rmvb", ".mov", ".avi", ".mpg", ".mpeg", ".wmv", ".mp4", ".divx", ".dvr-ms", ".wtv", ".ogm", ".ogv", ".asf", ".m4v", ".flv", ".f4v", ".3gp", ".webm", ".mts", ".m2v", ".rec" }; private static Dictionary GetVideoFileExtensionsDictionary() { var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (string ext in VideoFileExtensions) { dict[ext] = ext; } return dict; } private static readonly Dictionary VideoFileExtensionsDictionary = GetVideoFileExtensionsDictionary(); // http://en.wikipedia.org/wiki/Internet_media_type // Add more as needed private static Dictionary GetMimeTypeLookup() { var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); dict.Add(".jpg", "image/jpeg"); dict.Add(".jpeg", "image/jpeg"); dict.Add(".tbn", "image/jpeg"); dict.Add(".png", "image/png"); dict.Add(".gif", "image/gif"); dict.Add(".tiff", "image/tiff"); dict.Add(".webp", "image/webp"); dict.Add(".ico", "image/vnd.microsoft.icon"); dict.Add(".mpg", "video/mpeg"); dict.Add(".mpeg", "video/mpeg"); dict.Add(".ogv", "video/ogg"); dict.Add(".mov", "video/quicktime"); dict.Add(".webm", "video/webm"); dict.Add(".mkv", "video/x-matroska"); dict.Add(".wmv", "video/x-ms-wmv"); dict.Add(".flv", "video/x-flv"); dict.Add(".avi", "video/x-msvideo"); dict.Add(".asf", "video/x-ms-asf"); dict.Add(".m4v", "video/x-m4v"); dict.Add(".m4s", "video/mp4"); dict.Add(".cbz", "application/x-cbz"); dict.Add(".cbr", "application/epub+zip"); dict.Add(".epub", "application/epub+zip"); dict.Add(".pdf", "application/pdf"); dict.Add(".mobi", "application/x-mobipocket-ebook"); dict.Add(".ass", "text/x-ssa"); dict.Add(".ssa", "text/x-ssa"); return dict; } private static readonly Dictionary MimeTypeLookup = GetMimeTypeLookup(); private static readonly Dictionary ExtensionLookup = CreateExtensionLookup(); private static Dictionary CreateExtensionLookup() { var dict = MimeTypeLookup .GroupBy(i => i.Value) .ToDictionary(x => x.Key, x => x.First().Key, StringComparer.OrdinalIgnoreCase); dict["image/jpg"] = ".jpg"; dict["image/x-png"] = ".png"; return dict; } public static string GetMimeType(string path) { return GetMimeType(path, true); } /// /// Gets the type of the MIME. /// public static string GetMimeType(string path, bool enableStreamDefault) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException(nameof(path)); } var ext = Path.GetExtension(path) ?? string.Empty; if (MimeTypeLookup.TryGetValue(ext, out string result)) { return result; } // Type video if (StringHelper.EqualsIgnoreCase(ext, ".3gp")) { return "video/3gpp"; } if (StringHelper.EqualsIgnoreCase(ext, ".3g2")) { return "video/3gpp2"; } if (StringHelper.EqualsIgnoreCase(ext, ".ts")) { return "video/mp2t"; } if (StringHelper.EqualsIgnoreCase(ext, ".mpd")) { return "video/vnd.mpeg.dash.mpd"; } // Catch-all for all video types that don't require specific mime types if (VideoFileExtensionsDictionary.ContainsKey(ext)) { return "video/" + ext.TrimStart('.').ToLower(); } // Type text if (StringHelper.EqualsIgnoreCase(ext, ".css")) { return "text/css"; } if (StringHelper.EqualsIgnoreCase(ext, ".csv")) { return "text/csv"; } if (StringHelper.EqualsIgnoreCase(ext, ".html")) { return "text/html; charset=UTF-8"; } if (StringHelper.EqualsIgnoreCase(ext, ".htm")) { return "text/html; charset=UTF-8"; } if (StringHelper.EqualsIgnoreCase(ext, ".txt")) { return "text/plain"; } if (StringHelper.EqualsIgnoreCase(ext, ".log")) { return "text/plain"; } if (StringHelper.EqualsIgnoreCase(ext, ".xml")) { return "application/xml"; } // Type audio if (StringHelper.EqualsIgnoreCase(ext, ".mp3")) { return "audio/mpeg"; } if (StringHelper.EqualsIgnoreCase(ext, ".m4a")) { return "audio/mp4"; } if (StringHelper.EqualsIgnoreCase(ext, ".aac")) { return "audio/mp4"; } if (StringHelper.EqualsIgnoreCase(ext, ".webma")) { return "audio/webm"; } if (StringHelper.EqualsIgnoreCase(ext, ".wav")) { return "audio/wav"; } if (StringHelper.EqualsIgnoreCase(ext, ".wma")) { return "audio/x-ms-wma"; } if (StringHelper.EqualsIgnoreCase(ext, ".flac")) { return "audio/flac"; } if (StringHelper.EqualsIgnoreCase(ext, ".aac")) { return "audio/x-aac"; } if (StringHelper.EqualsIgnoreCase(ext, ".ogg")) { return "audio/ogg"; } if (StringHelper.EqualsIgnoreCase(ext, ".oga")) { return "audio/ogg"; } if (StringHelper.EqualsIgnoreCase(ext, ".opus")) { return "audio/ogg"; } if (StringHelper.EqualsIgnoreCase(ext, ".ac3")) { return "audio/ac3"; } if (StringHelper.EqualsIgnoreCase(ext, ".dsf")) { return "audio/dsf"; } if (StringHelper.EqualsIgnoreCase(ext, ".m4b")) { return "audio/m4b"; } if (StringHelper.EqualsIgnoreCase(ext, ".xsp")) { return "audio/xsp"; } if (StringHelper.EqualsIgnoreCase(ext, ".dsp")) { return "audio/dsp"; } // Playlists if (StringHelper.EqualsIgnoreCase(ext, ".m3u8")) { return "application/x-mpegURL"; } // Misc if (StringHelper.EqualsIgnoreCase(ext, ".dll")) { return "application/octet-stream"; } // Web if (StringHelper.EqualsIgnoreCase(ext, ".js")) { return "application/x-javascript"; } if (StringHelper.EqualsIgnoreCase(ext, ".json")) { return "application/json"; } if (StringHelper.EqualsIgnoreCase(ext, ".map")) { return "application/x-javascript"; } if (StringHelper.EqualsIgnoreCase(ext, ".woff")) { return "font/woff"; } if (StringHelper.EqualsIgnoreCase(ext, ".ttf")) { return "font/ttf"; } if (StringHelper.EqualsIgnoreCase(ext, ".eot")) { return "application/vnd.ms-fontobject"; } if (StringHelper.EqualsIgnoreCase(ext, ".svg")) { return "image/svg+xml"; } if (StringHelper.EqualsIgnoreCase(ext, ".svgz")) { return "image/svg+xml"; } if (StringHelper.EqualsIgnoreCase(ext, ".srt")) { return "text/plain"; } if (StringHelper.EqualsIgnoreCase(ext, ".vtt")) { return "text/vtt"; } if (StringHelper.EqualsIgnoreCase(ext, ".ttml")) { return "application/ttml+xml"; } if (enableStreamDefault) { return "application/octet-stream"; } return null; } public static string ToExtension(string mimeType) { if (string.IsNullOrEmpty(mimeType)) { throw new ArgumentNullException(nameof(mimeType)); } // handle text/html; charset=UTF-8 mimeType = mimeType.Split(';')[0]; if (ExtensionLookup.TryGetValue(mimeType, out string result)) { return result; } return null; } } }