|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Getting a file's ContentTypeI 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. Hello Nathan,
An excellent article on codeproject may help you. Here is the link: http://www.codeproject.com/dotnet/ContentType.asp Regards, Vaibhav "V" <vaibhav.gado***@gmail.com> wrote in message The trick mentioned works, but not always.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 safest way is to use this. http://technolog.nl/eprogrammer/archive/2005/12/12/415.aspx Egbert Nierop (MVP for IIS) wrote:
> "V" <vaibhav.gado***@gmail.com> wrote in message Just one problem with that technique - it's undefined whether it actually > 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 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
Show quote
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam> It uses allocated memory, in the buffer and it uses CoTaskMemAlloc, for the 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[], 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 That's why this declaration exists.> you're delete[]-ing it back into the same heap. [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 I agree, but you might agree with me, that the whole .NET framework, > correctly to be used outside a known environment. **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. 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; } -- Show quoteHTH, Kevin Spencer Microsoft MVP Professional Numbskull Hard work is a medication for which there is no placebo. "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/ >
Show quote
"Kevin Spencer" <kevin@DIESPAMMERSDIEtakempis.com> wrote in message Hi Kevin,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); outPtr leaks memory in your sample. You should free it using CoTaskMemFree... Cheers |
|||||||||||||||||||||||