Home All Groups Group Topic Archive Search About

Getting a file's ContentType

Author
10 May 2006 5:45 AM
Nathan Sokalski
I would like to be able to get the ContentType of a file programmatically
(for example, I want *.txt files to return "text/plain"). I could not find a
way to do this using VB.NET's classes, but I am also somewhat new to using
the System.IO namespace for anything other than text files and the pure
basics, so I could very well have missed it. Any help would be appreciated.
Thanks.
--
Nathan Sokalski
njsokal***@hotmail.com
http://www.nathansokalski.com/

Author
10 May 2006 6:18 AM
Kalpesh
Author
10 May 2006 6:21 AM
V
Hello Nathan,

An excellent article on codeproject may help you. Here is the link:
http://www.codeproject.com/dotnet/ContentType.asp

Regards,
Vaibhav
Author
10 May 2006 7:55 AM
Egbert Nierop (MVP for IIS)
"V" <vaibhav.gado***@gmail.com> wrote in message
news:1147242077.506470.316990@i39g2000cwa.googlegroups.com...
> Hello Nathan,
>
> An excellent article on codeproject may help you. Here is the link:
> http://www.codeproject.com/dotnet/ContentType.asp
>
> Regards,
> Vaibhav

The trick mentioned works, but not always.
The safest way is to use this.
http://technolog.nl/eprogrammer/archive/2005/12/12/415.aspx
Author
10 May 2006 1:51 PM
Carl Daniel [VC++ MVP]
Egbert Nierop (MVP for IIS) wrote:
> "V" <vaibhav.gado***@gmail.com> wrote in message
> news:1147242077.506470.316990@i39g2000cwa.googlegroups.com...
>> Hello Nathan,
>>
>> An excellent article on codeproject may help you. Here is the link:
>> http://www.codeproject.com/dotnet/ContentType.asp
>>
>> Regards,
>> Vaibhav
>
> The trick mentioned works, but not always.
> The safest way is to use this.
> http://technolog.nl/eprogrammer/archive/2005/12/12/415.aspx

Just one problem with that technique - it's undefined whether it actually
works.  FindMimeFromData returns memory allocated from the heap with new[],
so there's no way to correctly free that memory unless you can be sure
you're delete[]-ing it back into the same heap.

Despite being exported from the DLL, this function really wasn't written
correctly to be used outside a known environment.

-cd
Author
13 May 2006 8:26 PM
Egbert Nierop (MVP for IIS)
Show quote
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
wrote in message news:e1UgLjDdGHA.4932@TK2MSFTNGP03.phx.gbl...
> Egbert Nierop (MVP for IIS) wrote:
>> "V" <vaibhav.gado***@gmail.com> wrote in message
>> news:1147242077.506470.316990@i39g2000cwa.googlegroups.com...
>>> Hello Nathan,
>>>
>>> An excellent article on codeproject may help you. Here is the link:
>>> http://www.codeproject.com/dotnet/ContentType.asp
>>>
>>> Regards,
>>> Vaibhav
>>
>> The trick mentioned works, but not always.
>> The safest way is to use this.
>> http://technolog.nl/eprogrammer/archive/2005/12/12/415.aspx
>
> Just one problem with that technique - it's undefined whether it actually
> works.  FindMimeFromData returns memory allocated from the heap with
> new[],

It uses allocated memory, in the buffer and it uses CoTaskMemAlloc, for the
mimetype string. If that were a new operator, well, I'm sure that's
compatible since the C++ new keyword, after all, just uses *the same* memory
allocator (ie HeapAlloc).

> so there's no way to correctly free that memory unless you can be sure
> you're delete[]-ing it back into the same heap.


That's why this declaration exists.
  [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1,
SizeParamIndex = 3)] byte[] pBuffer,
      int cbSize,



if it were wrong, then MS would not support it. And besides, it never failed
in my runtime.


> Despite being exported from the DLL, this function really wasn't written
> correctly to be used outside a known environment.

I agree, but you might agree with me, that the whole .NET framework,
**depends** on unmanaged code, from kernel, ADSI, WMI etc, and originally,
these were never made with .NET in mind. It's the other way around, .NET was
made to interop with them. So I won't hesitate to use this code, unless you
have a proven example, that shows that it will go wrong.

Maybe a CoTaskMemAlloc would be better instead of a byte[] array, but that
won't interop with FileRead...


Here you have the generated ASM listing.
00000107 FF 75 B8 push dword ptr [ebp-48h]
0000010a 56 push esi
0000010b 6A 00 push 0
0000010d 6A 00 push 0
0000010f 8D 45 B4 lea eax,[ebp-4Ch]
00000112 50 push eax
00000113 6A 00 push 0
00000115 8B D7 mov edx,edi
00000117 33 C9 xor ecx,ecx
00000119 E8 1A 2C 86 FF call FF862D38  <-- call FindMimeFromData

and here is the IL

  IL_0052:  ldsfld     native int [mscorlib]System.IntPtr::Zero
  IL_0057:  ldarg.0
  IL_0058:  ldloc.2
  IL_0059:  ldloc.0
  IL_005a:  ldnull
  IL_005b:  ldc.i4.0
  IL_005c:  ldloca.s   V_3
  IL_005e:  ldc.i4.0
  IL_005f:  call       int32 TimeStampTester.Class1::FindMimeFromData(native
int, string,uint8[], int32, string, int32, string&, int32)

As you can see, the compiler does not -worry- about packing the byte array
into something else! It just assumes, that during the Pinvoke, the memory
won't move. Now this is interesting. If I have the wrong approach, then MS
introduced a dangerous bug, by allowing us to program like this.
Author
10 May 2006 11:38 AM
Kevin Spencer
The following uses Internet Explorer to find the MIME type:

[DllImport("urlmon.dll", CharSet = CharSet.Auto)]
static extern int FindMimeFromData(IntPtr pBC, IntPtr pwzUrl, byte[]
pBuffer, int cbSize,
   IntPtr pwzMimeProposed, int dwMimeFlags, out IntPtr ppwzMimeOut, int
dwReserved);

/// <summary type="System.String">
/// Figures out the Content Type from a File Name
/// </summary>
/// <param name="FileName">File Name to detect</param>
/// <returns>Content Type as string</returns>
/// <remarks>The Windows API has the functionality to detect the file type
of
/// any file type registered with the Operating System. This method makes an
API
/// call to get the MIME type of the file from the
<var>FileName</var></remarks>
public string MimeTypeFromFileName(string FileName)
{
    byte[] dataBytes = Encoding.ASCII.GetBytes(FileName);
    if (dataBytes == null)
        throw new ArgumentNullException("dataBytes");
    string mimeRet = String.Empty;
    IntPtr suggestPtr = IntPtr.Zero, filePtr = IntPtr.Zero, outPtr =
IntPtr.Zero;
    int ret = FindMimeFromData(IntPtr.Zero, IntPtr.Zero, dataBytes,
dataBytes.Length, suggestPtr, 0, out outPtr, 0);
    if (ret == 0 && outPtr != IntPtr.Zero)
    {
        return Marshal.PtrToStringUni(outPtr);
    }
    return mimeRet;
}

--
HTH,

Kevin Spencer
Microsoft MVP
Professional Numbskull

Hard work is a medication for which
there is no placebo.

Show quote
"Nathan Sokalski" <njsokal***@hotmail.com> wrote in message
news:u7BTyT$cGHA.1324@TK2MSFTNGP04.phx.gbl...
>I would like to be able to get the ContentType of a file programmatically
>(for example, I want *.txt files to return "text/plain"). I could not find
>a way to do this using VB.NET's classes, but I am also somewhat new to
>using the System.IO namespace for anything other than text files and the
>pure basics, so I could very well have missed it. Any help would be
>appreciated. Thanks.
> --
> Nathan Sokalski
> njsokal***@hotmail.com
> http://www.nathansokalski.com/
>
Author
17 May 2006 3:08 PM
Egbert Nierop (MVP for IIS)
Show quote
"Kevin Spencer" <kevin@DIESPAMMERSDIEtakempis.com> wrote in message
news:%23$XP2YCdGHA.380@TK2MSFTNGP04.phx.gbl...
> The following uses Internet Explorer to find the MIME type:
>
> [DllImport("urlmon.dll", CharSet = CharSet.Auto)]
> static extern int FindMimeFromData(IntPtr pBC, IntPtr pwzUrl, byte[]
> pBuffer, int cbSize,
>   IntPtr pwzMimeProposed, int dwMimeFlags, out IntPtr ppwzMimeOut, int
> dwReserved);
>
> /// <summary type="System.String">
> /// Figures out the Content Type from a File Name
> /// </summary>
> /// <param name="FileName">File Name to detect</param>
> /// <returns>Content Type as string</returns>
> /// <remarks>The Windows API has the functionality to detect the file type
> of
> /// any file type registered with the Operating System. This method makes
> an API
> /// call to get the MIME type of the file from the
> <var>FileName</var></remarks>
> public string MimeTypeFromFileName(string FileName)
> {
>    byte[] dataBytes = Encoding.ASCII.GetBytes(FileName);
>    if (dataBytes == null)
>        throw new ArgumentNullException("dataBytes");
>    string mimeRet = String.Empty;
>    IntPtr suggestPtr = IntPtr.Zero, filePtr = IntPtr.Zero, outPtr =
> IntPtr.Zero;
>    int ret = FindMimeFromData(IntPtr.Zero, IntPtr.Zero, dataBytes,
> dataBytes.Length, suggestPtr, 0, out outPtr, 0);


Hi Kevin,
outPtr leaks memory in your sample. You should free it using
CoTaskMemFree...

Cheers

AddThis Social Bookmark Button