Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Determine MIME type

44 views
Skip to first unread message

Bryan Valencia

unread,
Jan 4, 2005, 7:42:44 PM1/4/05
to
How do I take a file name and determine the file's MIME type?

I have an interface where any file can be dragged and dropped into my
interface, and I must know the mime type to post it at it's destination.

I'd like to politely ask Windows to give me this information rather than
having to code it all into my application.

:)


Alexander Fediachov

unread,
Jan 4, 2005, 7:57:50 PM1/4/05
to
function GetFileMIMEType(const FName: String): String;
var
Registry: TRegistry;
ext: String;
begin
Result := '';
ext := ExtractFileExt(FName);
Registry := TRegistry.Create;
try
Registry.RootKey := HKEY_CLASSES_ROOT;
if Registry.KeyExists(ext) then
begin
Registry.OpenKey(ext, false);
Result := Registry.ReadString('Content Type');
Registry.CloseKey;
end;
finally
Registry.Free;
end;
end;


--
Sincerely,
Alexander Fediachov
Fast Reports Inc
Solutions for developers: Report server and Reporting tools
http://www.fast-report.com

Remy Lebeau (TeamB)

unread,
Jan 4, 2005, 8:36:32 PM1/4/05
to

"Alexander Fediachov" <fedi...@fast-report.com> wrote in message
news:41db3b5b$1...@newsgroups.borland.com...

> function GetFileMIMEType(const FName: String): String;

Not all MIME types are registered that way. You missed the second area of
the Registry where MIME types are registered. See my other reply.


Gambit


Remy Lebeau (TeamB)

unread,
Jan 4, 2005, 8:35:27 PM1/4/05
to

"Bryan Valencia" <borng.so...@spamgourmet.com> wrote in message
news:41db36ea$1...@newsgroups.borland.com...

> How do I take a file name and determine the file's MIME type?

Look up the file extension in the Registry. There are two places that you
can look:

1) under the HKEY_CLASSES_ROOT key, each extension has its own subkey. Some
extensions have a "Content Type" value available.

2) Also under HKEY_CLASSES_ROOT is a "MIME\Database\Content Type" subkey.
Each key under that is a MIME type with a an "Extension" value available.

> I'd like to politely ask Windows to give me this information
> rather than having to code it all into my application.

Sorry, but you will have to code it manually. Windows has no provisions for
such a query.

Of course, you could use Indy, which can do the lookup for you. It also
hard-codes many common MIME types that may or may not exist in the Registry.


Gambit


Bryan Valencia

unread,
Jan 6, 2005, 4:53:28 PM1/6/05
to
Thanks for the rapid help...

Yesterday I found the info in the registry and did this: instead of looking
under HKEY_CLASSES_ROOT, I looked in HKEY_LOCAL_MACHINE.

I found it odd that the constants for the HKEY_ variables were in the
WINDOWS unit and not the REGISTRY unit. There should be something in the
help about that.

---
function GetMIMEtype(FileName:String):String;
var
reg:TRegistry;
ans:String;
ext:string;
begin
ans:='';
reg:=TRegistry.Create;
try
ext:=ExtractFileExt(Filename);

reg.RootKey := HKEY_LOCAL_MACHINE;
if reg.OpenKeyReadOnly('\SOFTWARE\Classes\'+ext+'\') then
begin
ans:=reg.ReadString('Content Type');
end;
finally
reg.Free;
end;

if ans='' then ans:='application/octet-stream';
result:=ans;
end;

Ozz Nixon [BPDX]

unread,
Jan 10, 2005, 9:40:11 AM1/10/05
to
Just an observation, but that is not the best way for your application
to implement MIME-Tables, especially if you plan to distribute your
application to other users. I do not use Indy (for obvious reasons), but
I am sure Chad and his guys have done the same that we did - there are
online DB's for MIME lookup. Most are not complete, but if you collect
enough of them - or partner w/ Netscape or the Apache crew - you will
end up with a very complete listing.

Per coding this... [not a suggestion, but a lazy mans way out] - do
something as simple as store the data in
Uppercase(Extension)+'='+MimeString;

Then using a TStringList, load from file - and simple use the values[]
to get to your data. Having a fail-safe if the result='' then
result='application/octet-stream';

In the Winshock project - we coded all of this into a stand-alone unit
that uses a B-Tree in memory for performance, and a
DXDataSetMemoryStream to store and retreive from disk. ... if you are
stuck on gettng this coded, let me know - and I will send you
MimeCode.PAS and wrap it up for you.

Ozz
www.dxsock.com

Remy Lebeau (TeamB)

unread,
Jan 10, 2005, 2:30:50 PM1/10/05
to

"Bryan Valencia" <borng.so...@spamgourmet.com> wrote in message
news:41ddb237$1...@newsgroups.borland.com...

> instead of looking under HKEY_CLASSES_ROOT, I looked
> in HKEY_LOCAL_MACHINE.

Why? They are not stored in HKEY_LOCAL_MACHINE. HKEY_CLASSES_ROOT is the
correct key to look under. I verified it on machines running three
different OSes. What I told you earlier is where you should be looking.

> I found it odd that the constants for the HKEY_ variables were in
> the WINDOWS unit and not the REGISTRY unit. There should
> be something in the help about that.

No, there should not. They are declared in the Windows unit because that is
where they belong. They are Win32 API variables, not VCL variables. The
Windows unit contains all of the Win32 API defines. The Registry unit is a
VCL unit, not a Win32 unit.

> function GetMIMEtype(FileName:String):String;

That code is wrong. You are using the wrong key, and you did not look in
the second key like I suggested earlier. The root level of
HKEY_CLASSES_ROOT does not contain all of the available MIME types. The
MIME database can contain types that the root level does not.

> reg.RootKey := HKEY_LOCAL_MACHINE;
> if reg.OpenKeyReadOnly('\SOFTWARE\Classes\'+ext+'\') then

That key maps directly to the HKEY_CLASSES_ROOT key. Always access
HKEY_CLASSES_ROOT directly, not via HKEY_LOCAL_MACHINE.

Use this code instead:

function GetMIMEType(FileName: String): String;
var
reg: TRegistry;
ext: String;
list: TStringList;
begin
Result := '';
ext := LowerCase(ExtractFileExt(Filename));
reg := TRegistry.Create;
try
reg.RootKey := HKEY_CLASSES_ROOT;
if reg.OpenKeyReadOnly('\' + ext) then begin
Result := reg.ReadString('Content Type');
reg.CloseKey;
end;
if Result = '' then begin
if reg.OpenKeyReadOnly('\MIME\Database\Content Type') then
begin
list := TStringList.Create;
try
reg.GetKeyNames(list);
for i := 0 to list.Count - 1 do begin
if Reg.OpenKeyReadOnly('\MIME\Database\Content
Type\' + list[i]) then begin
if AnsiSameText(ext,
reg.ReadString('Extension')) then begin
Result := list[i];
Break;
end;
end;
end;
finally
list.Free;
end;
reg.CloseKey;
end;
end;
finally
reg.Free;
end;
if Result = '' then Result := 'application/octet-stream';
end;


Gambit


Remy Lebeau (TeamB)

unread,
Jan 10, 2005, 2:29:59 PM1/10/05
to

"Ozz Nixon [BPDX]" <ozz_...@hotmail.com> wrote in message
news:41e293c6$1...@newsgroups.borland.com...

> Just an observation, but that is not the best way for your application
> to implement MIME-Tables, especially if you plan to distribute your
> application to other users. I do not use Indy (for obvious reasons),
> but I am sure Chad and his guys have done the same that we did -
> there are online DB's for MIME lookup.

You assume incorrectly. Indy does not perform online lookups. Indy
maintains its own global TStringList of available MIME types. That list is
initially filled with hard-coded known types. Then the list is updated with
the current registrations from the OS when needed. Under Windows, the
registrations come from the Registry. Under Linux, they come from text
files named "mime.types" that are located in up to three different locations
on the file system.

> Per coding this... [not a suggestion, but a lazy mans way out] - do
> something as simple as store the data in
> Uppercase(Extension)+'='+MimeString;
>
> Then using a TStringList, load from file - and simple use the
> values[] to get to your data. Having a fail-safe if the result=''
> then result='application/octet-stream';

That is exactly what Indy does. It simply does not get the data from
online, but from the local machine instead.


Gambit


Bryan Valencia

unread,
Jan 11, 2005, 3:02:15 PM1/11/05
to
Thanks for all your answers.

1. I do not wish to maintain a global list of MIME types, either on the
desktops, on the internet, or some shared drive. The local machine will be
more than adequate for this task.

2. I used HKEY_LOCAL_MACHINE because when I opened regedit and hunted for
the values, that's where they were first found. I implemented this before I
got any answers from you guys. It also appears to be true for both NT and
2000, which are my 'universe' at present.


P.S.
You know, I have said this for years, but the Borland community is what
makes Delphi a superior product. If you have ever asked a question on the
MS NGs, you'll know what I mean.


Remy Lebeau (TeamB)

unread,
Jan 11, 2005, 4:49:04 PM1/11/05
to

"Bryan Valencia" <borng.so...@spamgourmet.com> wrote in message
news:41e42f99$1...@newsgroups.borland.com...

> 1. I do not wish to maintain a global list of MIME types, either
> on the desktops, on the internet, or some shared drive. The local
> machine will be more than adequate for this task.

I never said for you to store your own global list.

> 2. I used HKEY_LOCAL_MACHINE because when I opened
> regedit and hunted for the values, that's where they were first found.

They would have been found in HKEY_CLASSES_ROOT first, since that is the
first key listed in the Registry.

> I implemented this before I got any answers from you guys. It also
> appears to be true for both NT and 2000, which are my 'universe'
> at present.

What I have described to you is true for all Windows versions, from Win95 up
to Win2003.


Gambit


0 new messages