拡張子からのMIMEタイプの取得
Windowsの場合、レジストリのHKEY_CLASSES_ROOTに、拡張子毎にアプリケーションの関連付けなどの情報が格納されている。 目的の拡張子をキーとしたノードにContent Typeの値が登録されている場合は、その値を使用できる。
レジストリを参照して拡張子からMIMEタイプを取得する
using System;
using Microsoft.Win32;
class Sample {
private static string GetMimeTypeByExtension(string extension)
{
const string defaultType = "application/octet-stream";
var key = Registry.ClassesRoot.OpenSubKey(extension);
if (key == null)
return defaultType;
var mimeType = key.GetValue("Content Type");
if (mimeType == null)
return defaultType;
else
return (string)mimeType;
}
static void Main(string[] args)
{
var extensions = new[] {
".txt", ".eml", ".html",
".jpg", ".bmp", ".wav",
".mp4",
".exe", ".dll", ".bin",
".zip", ".tar.gz",
};
foreach (var extension in extensions) {
Console.WriteLine("{0} => {1}", extension, GetMimeTypeByExtension(extension));
}
}
}
レジストリを参照して拡張子からMIMEタイプを取得する
Imports System
Imports Microsoft.Win32
Class Sample
Private Shared Function GetMimeTypeByExtension(ByVal extension As String) As String
Const defaultType As String = "application/octet-stream"
Dim key As RegistryKey = Registry.ClassesRoot.OpenSubKey(extension)
If key Is Nothing Then Return defaultType
Dim mimeType As Object = key.GetValue("Content Type")
If mimeType Is Nothing Then
Return defaultType
Else
Return CStr(mimeType)
End If
End Function
Shared Sub Main()
Dim extensions As String() = New String() {
".txt", ".eml", ".html", _
".jpg", ".bmp", ".wav", _
".mp4", _
".exe", ".dll", ".bin", _
".zip", ".tar.gz" _
}
For Each extension As String In extensions
Console.WriteLine("{0} => {1}", extension, GetMimeTypeByExtension(extension))
Next
End Sub
End Class
実行結果
.txt => text/plain .eml => message/rfc822 .html => text/html .jpg => image/jpeg .bmp => image/bmp .wav => audio/wav .mp4 => video/mp4 .exe => application/x-msdownload .dll => application/x-msdownload .bin => application/octet-stream .zip => application/x-zip-compressed .tar.gz => application/octet-stream
データストリームからのMIMEタイプの判定
FindMimeFromData関数を用いることで、データストリームからMIMEタイプを推定することが出来る。
(この項の内容は検証が不十分です。 適用に際してはリンク先のドキュメントを参照してください。)
FindMimeFromDataを使ってデータストリームからMIMEタイプを推定する
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
class Sample {
private enum FMFD : uint {
FMFD_DEFAULT = 0,
FMFD_URLASFILENAME = 1 << 0,
FMFD_ENABLEMIMESNIFFING = 1 << 1,
FMFD_IGNOREMIMETEXTPLAIN = 1 << 2,
FMFD_SERVERMIME = 1 << 3, // ?
}
[DllImport("urlmon")] private static extern
uint FindMimeFromData(IntPtr pBC,
IntPtr pwzUrl,
byte[] buffer,
int cbSize,
[In, MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
FMFD dwMimeFlags,
[MarshalAs(UnmanagedType.LPWStr)] out string ppwzMimeOut,
uint dwReserved);
private static string GetMimeTypeByMagic(byte[] magic, string mimeProposed)
{
const uint E_INVALIDARG = 0x80070057;
string mime;
var ret = FindMimeFromData(IntPtr.Zero, IntPtr.Zero, magic, magic.Length, mimeProposed, FMFD.FMFD_DEFAULT, out mime, 0);
if (ret == 0)
return mime;
else if (ret == E_INVALIDARG)
throw new ArgumentException();
else
return null;
}
static void Main()
{
var image = new Bitmap(8, 8);
// イメージ
foreach (var format in new[] {
System.Drawing.Imaging.ImageFormat.Bmp,
System.Drawing.Imaging.ImageFormat.Jpeg,
System.Drawing.Imaging.ImageFormat.Png,
}) {
using (var stream = new MemoryStream()) {
image.Save(stream, format);
Console.WriteLine("{0} => {1}", format, GetMimeTypeByMagic(stream.ToArray(), null));
}
}
// プレーンテキスト
var text = "Hello, world.\r\n";
Console.WriteLine("plain text => {0}", GetMimeTypeByMagic(Encoding.Default.GetBytes(text), "text/plain"));
// XML (Atomフィード)
text = @"<?xml version=""1.0""?>
<feed xmlns=""http://www.w3.org/2005/Atom"">
</feed>
</xml>";
Console.WriteLine("XML => {0}", GetMimeTypeByMagic(Encoding.Default.GetBytes(text), "text/plain"));
// HTML
text = @"<html><body>HTML</body></html>";
Console.WriteLine("HTML => {0}", GetMimeTypeByMagic(Encoding.Default.GetBytes(text), "text/plain"));
// 256バイトのランダムなストリーム
var random = new Random();
for (var act = 0; act < 3; act++) {
var stream = new byte[0x100];
random.NextBytes(stream);
Console.WriteLine("random => {0}", GetMimeTypeByMagic(stream, "application/octet-stream"));
}
}
}
実行結果
Bmp => image/bmp Jpeg => image/pjpeg Png => image/x-png plain text => text/plain XML => text/xml HTML => text/html random => application/octet-stream random => application/octet-stream random => application/octet-stream
FindMimeFromDataは、渡されたデータストリームをスキャンしてMIME Type Detection in Internet ExplorerのKnown MIME Typesにあるタイプかどうかテストする。 このページには判定方法についての詳細が書かれている。
FindMimeFromDataは、通常最初の256バイトの内容を重視するとしているので、例えば256バイトを越えるファイルの内容をすべて渡すのは無駄と思われる。