request verification on code

edited March 11, 2016 11:22AM in PInvoke.Net
I'm new to .NET C# and am working on a project involving the uploading of files. I usually program in Java, so this is a bit foreign to me. I came across a post concerning this on StackOvervlow which led me to download PInvoke. I'm accessing urlmon.dll through my Visual Studio and I'm trying to determine the mime type of a file that has been uploaded using HttpPostedFile. I'm wondering if the following will work. It certainly seems to compile fine, but I don't know if it will work at runtime. I'm concerned with method GetMimeFromFile(Stream filestream).

HttpPostedFile has a property InputStream that returns a Stream object so I'm simply assigning it to the parameter of the method GetMimeFromFile.

Looking at the statement:

using (var fs = filestream)
{ ... }

This is usually how you open a stream, read it in, then it closes automatically. I'm thinking that this will close the stream prematurely once the mimetype has been discovered. You see, getting the mimetype is just part of a validation process. Once completed, I must pass the Stream object on to have the file stored in a directory on the server or in a database. So the Stream will be read in a second and final time. Should I be recoding this so that the stream isn't closed? Please advise.
private String getFileMimeType(HttpPostedFile item)
{
   String type = "";
    	    
    try
    {               
         type =  UrlmonMimeDetect.GetMimeFromFile(item.InputStream);               
    }
    catch(Exception e)
    {
	    log.Error(e.StackTrace);
    }
    	    
    return type;
}

...

internal class UrlmonMimeDetect
    {
        [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
        private static extern int FindMimeFromData(IntPtr pBC,
            [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
            [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 3)] byte[] pBuffer,
            int cbSize,
            [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
            int dwMimeFlags,
            out IntPtr ppwzMimeOut,
            int dwReserved);

        private static readonly ILog log = LogManager.GetLogger(typeof(UrlmonMimeDetect));

        
        public static string GetMimeFromFile(Stream filestream)
        {

            const int maxContent = 256;
            var buffer = new byte[maxContent];
            var mimeTypePtr = IntPtr.Zero;

            try
            {
               using (var fs = filestream)
               {
                   if (fs.Length >= maxContent)
                       fs.Read(buffer, 0, maxContent);
                   else
                       fs.Read(buffer, 0, (int)fs.Length);
               }
            }
            catch(Exception e)
            {
                log.Error(e.StackTrace);
            }

            try
            {
               var result = FindMimeFromData(IntPtr.Zero, null, buffer, maxContent, null, 0, out mimeTypePtr, 0);
               if (result != 0)
               {
                    Marshal.FreeCoTaskMem(mimeTypePtr);
                    throw Marshal.GetExceptionForHR(result);
               }

                var mime = Marshal.PtrToStringUni(mimeTypePtr);
                Marshal.FreeCoTaskMem(mimeTypePtr);
                return mime;
            }
            catch (Exception)
            {
                if (mimeTypePtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(mimeTypePtr);
                }
                return "unknown/unknown";
            }
        }
    }
Sign In or Register to comment.