locked
FileUpload ContentType trickery RRS feed

  • Question

  • User1090916182 posted

    I am developing an app where a user uploads PDF files to the server, via a FileUpload control.

    As part of the usual security/reliability checks I wanted to verify that the uploaded document was actually a PDF, not just say, a Text file renamed to have a .PDF extension.

    I thought this might work:

    If Not FileUploadControl.PostedFile.ContentType.ToLower = "application/pdf" Then
    	ltl_status.Text = "<p>Error - The upload file must be in PDF format.</p>"
    	Exit Sub
    End If
    The above code however is fooled if I rename a Text file with a PDF extension and upload it.  Is there anyway to actually check the real type of the file instead of just presuming the file extension is accurate?
    Thursday, October 9, 2008 2:11 PM

Answers

  • User915387828 posted

    Hi Rouchie,

    You can detect the file header encode, because different file have different one.

    Here is the code, you can try it.

        protected void Button1_Click(object sender, EventArgs e)
        {
            System.IO.BinaryReader r = new System.IO.BinaryReader(FileUpload2.PostedFile.InputStream);
            string fileclass = "";
            byte buffer;
            try
            {
                buffer = r.ReadByte();
                fileclass = buffer.ToString();
                buffer = r.ReadByte();
                fileclass += buffer.ToString();
            }
            catch
            {
            }
            r.Close();
            if(fileclass!=“3780”)
            {
                ltl_status.Text = "<p>Error - The upload file must be in PDF format.</p>"
                return;
            }
        }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, October 14, 2008 1:01 AM

All replies

  • User1485238302 posted

    I have not tried this but have you tried using this instead: 

    System.IO.Path.GetExtension(strPostedFileName)

     Example given here:

    http://aspalliance.com/1614_Adding_Filter_Action_to_FileUpload_Control_of_ASPNET_20.all#Page4

    Thursday, October 9, 2008 2:28 PM
  • User-99544339 posted

     I Just tried your case with the ContentType and it will work, even if I changed the extension the contenttype will be te same. So your piece of code should work.

    Thursday, October 9, 2008 2:40 PM
  • User1090916182 posted

     I Just tried your case with the ContentType and it will work, even if I changed the extension the contenttype will be te same. So your piece of code should work.

     

    Okay so perhaps something is wrong.  Please follow these steps to reproduce the problem:

    1. Create a text file on the desktop
    2. Fill with some placeholder text and save as TEST.TXT
    3. Rename the file to TEST.PDF
    4. Create a quick page with this code:
       
      Protected Sub UploadDocument(ByVal sender As Object, ByVal e As EventArgs) Handles btn_upload.Click
      Trace.Warn("ContentType is: " & myFileUpload.PostedFile.ContentType)
      End Sub
       
    5. When you upload the TEST.PDF file, the trace shows the ContentType as application/pdf when it fact it should be text/plain because of how we created the file.
    Friday, October 10, 2008 3:38 AM
  • User-99544339 posted

    Oke I get the same results as you now, I did it the other way around. I created a pdf and uploaded it result application/pdf renamed it to txt and the result was also application/pdf. From txt to pdf is doesn't work and I also tested doc to pdf doesn't worked also. I think the ContentType in this case is useless or has some one another idea?

    Friday, October 10, 2008 3:56 AM
  • User1090916182 posted

    Oke I get the same results as you now... I think the ContentType in this case is useless or has some one another idea?

     

    Thanks for clarifying the problem.  

    I did some reading on MSDN and it appears that the ContentType is set by the client and not the server!  Therefore I don't think this issue can be solved unless there is MIME detection somewhere within the .NET Framework...?!?

    Friday, October 10, 2008 4:35 AM
  • User915387828 posted

    Hi Rouchie,

    You can detect the file header encode, because different file have different one.

    Here is the code, you can try it.

        protected void Button1_Click(object sender, EventArgs e)
        {
            System.IO.BinaryReader r = new System.IO.BinaryReader(FileUpload2.PostedFile.InputStream);
            string fileclass = "";
            byte buffer;
            try
            {
                buffer = r.ReadByte();
                fileclass = buffer.ToString();
                buffer = r.ReadByte();
                fileclass += buffer.ToString();
            }
            catch
            {
            }
            r.Close();
            if(fileclass!=“3780”)
            {
                ltl_status.Text = "<p>Error - The upload file must be in PDF format.</p>"
                return;
            }
        }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, October 14, 2008 1:01 AM
  • User1090916182 posted

    You can detect the file header encode....

     

    Hi

    Thanks for that code - it works perfectly.  Could you please tell me where I can find out how to check other file types using this method?  For example, you use 3780 for PDF files.  Is there somewhere where I can see other codes?

    Thank you.

    P.S.  Here is the VB.NET translation for anyone else who might need it...

     

    	Protected Function isPDF(ByVal myFile As HttpPostedFile) As Boolean
    Dim
    r As New System.IO.BinaryReader(myFile.InputStream)
    Dim fileclass As String = String.Empty
    Dim buffer As Byte
    Try

    buffer = r.ReadByte()
    fileclass = buffer.ToString
    buffer = r.ReadByte
    fileclass &= buffer.ToString
    Catch ex As Exception
    Throw ex
    Finally
    r.Close()
    End Try
    Return
    (fileclass = "3780")
    End Function
      
    Tuesday, October 14, 2008 4:03 AM
  • User915387828 posted

    Hi Rouchie,

    You can upload the related file, and set breakpoint and get the header code.

    Then you can use it to check the file type.

    Tuesday, October 14, 2008 4:23 AM
  • User1090916182 posted

    Okay, thanks.

    If you ever find a site where somebody has already done this for the various file types available, please let me know...!  [:)]

    Tuesday, October 14, 2008 5:34 AM
  • User-1367805312 posted

     Here you go... this should help some of you out

    208207  =  .doc
    7173   =   .gif
    255216   =   .jpg
    6677   =   .bmp
    13780   =   .png

    Saturday, February 7, 2009 2:28 AM
  • User-875597977 posted

    Hello Rouchie 

    I m new to this forum. I to faced the same problem.Actually i need to upload a .txt file,a .xls file and a .csv file.But this header keeps on changing with .txt files.Can u please guide me as to how to make sure that only the text,excel or csv files are only allowed and no other file.

    Thanks in advance

    Regards

    Jatinder Walia

    Wednesday, January 13, 2010 1:14 AM
  • User-875597977 posted

    Hello Hua-Jun Li

    I m new to this forum. I too am facing the same problem.In my case,I have to upload a textfiles file,excel files,csv files and the processing for each of these file types on server is different.Now i am getting different header encode values for text files containing different text.Please help.

    Thanks in advance

    Regards

    Jatinder Walia

    Wednesday, January 13, 2010 1:21 AM
  • User1090916182 posted

    I now use a different approach that simply checks the file extension.  Its not as thorough, but it much easier to use and provides an equivalent output:


    Public Shared Function IsFileExtensionAllowed(ByVal FileName As String) As Boolean
        Dim fileExt As String = System.IO.Path.GetExtension(FileName)
        Select Case fileExt.ToLower
            Case ".txt", ".xls", ".csv" ' also add ".xlsx" for Excel 2007 files
                Return True
            Case Else
                Return False
        End Select
    End Function


    To use this function do this:

    If IsFileExtensionAllowed(myFileUpload.PostedFile.FileName) Then
        ' save file
    Else
        myLabel.Text = "This type of file is not allowed!"
    End If

    Public Shared Function IsFileExtensionAllowed(ByVal FileName As String) As Boolean
                Dim fileExt As String = System.IO.Path.GetExtension(FileName)
                Select Case fileExt.ToLower
                    Case ".asp", ".aspx", ".vb", ".cs", ".dll", ".exe", ".pif", ".scr", ".vbs", ".bat", ".chm", ".cmd", ".com", ".cpl", ".ocx", ".reg"
                        Return False
                    Case Else
                        Return True
                End Select
            End Function
    Wednesday, January 13, 2010 4:55 AM
  • User604186779 posted

    Why can't - REGEX or some javascript check this

    http://venkat-dotnetsnippets.blogspot.com/2009/04/validation-for-fileuploadcontrol.html

    Wednesday, January 13, 2010 5:07 AM
  • User604186779 posted

    Why can't - REGEX or some javascript check this

    http://venkat-dotnetsnippets.blogspot.com/2009/04/validation-for-fileuploadcontrol.html

    Wednesday, January 13, 2010 5:08 AM
  • User-875597977 posted

    Wel to begin with,thanks for having helped my cause.Next,in my case this approach can't work...cos i know from my experience that users have a tendendency to experiement with your software.Now what i ,as a user will do is change the extension of an exe or say a .jpg file to .txt or .xls and upload the file.Please suggest what to do now.

    Thursday, January 14, 2010 12:59 AM
  • User-875597977 posted

    Thanks for having spared a fews seconds of your precious time for me.However,this solution doesn't see to work for me  cos i know from my experience that users have a tendendency to experiement with your software.Now what i ,as a user will do is change the extension of an exe or say a .jpg file to .txt or .xls and upload the file.Please suggest what to do now. Is there no way of looking at a file's internal content and identify what is it's file type?

    Thursday, January 14, 2010 1:03 AM
  • User-875597977 posted

    True,but the content-type property is same for .xls file and .exe file.So how does the server get to know whether the file being currently uploaded is an excel file or .exe file?

     

    .xls file            application/octet-stream

    .exe file           application/octet-stream

    Thursday, January 14, 2010 1:10 AM
  • User1090916182 posted

    If users are changing the file extension then you have no choice but to use the orginal posted solution by Hua-Jun Li - MSFT which checks the file encode headers.  The problem is that you would have to find these numbers out manually for each file type because I've never been able to find a list compiled.

    Please note though that if a user changes a file extension, then that's their problem not yours.  The server will never run a file on the actually server (with some minor exceptions like .ASPX or .HTML), so you just have to check that the file isn't one that can be run online by the server.

    Thursday, January 14, 2010 3:49 AM
  • User1763172376 posted
    i am following code, but after upload all files become occupted with file size  0. plz help.

    Protected Function
    isPDF(ByVal myFile As HttpPostedFile) As Boolean
    Dim
    r As New System.IO.BinaryReader(myFile.InputStream)
    Dim fileclass As String = String.Empty
    Dim buffer As Byte
    Try

    buffer = r.ReadByte()
    fileclass = buffer.ToString
    buffer = r.ReadByte
    fileclass &= buffer.ToString
    Catch ex As Exception
    Throw ex
    Finally
    r.Close()
    End Try
    Return
    (fileclass = "3780")
    End Function
    Wednesday, February 10, 2010 3:14 AM
  • User915387828 posted

    Hi sagnikmukh,

    Sorry about that.

    You should add the following code to judge whether the posted file exist.

    if (((fileUpload1.PostedFile == null)|| (string.IsNullOrEmpty(fileUpload1.PostedFile.FileName)|| (fileUpload1.PostedFile.InputStream == null))))
            {

    //your code.

    }

    Wednesday, February 10, 2010 3:31 AM
  • User1763172376 posted

    thanks for ur quick reply,

    i already declared

    If FileUpload1.HasFile Then
                Try

    ............

    here i call the function to check file type.

    ..............

    ..............


    using breck point, duing debug i can find value 3780 for PDF file, but in destination folder, the copid file corrupt and size 0kb.


    Wednesday, February 10, 2010 3:38 AM
  • User915387828 posted

    Hi sagnikmukh,

    If the file size is 0kb, you can give up it by using the 'if' judgement sentence.

    Wednesday, February 10, 2010 3:44 AM
  • User-1725231675 posted

    I too have been struggling with the same issue and ran across a library that seems to do the trick.

    http://www.netomatix.com/Products/DocumentManagement/MimeDetector.aspx

    If you want to encapsulate it and use a stream you can use this code:

    public MimeType GetMimeType(Stream objInputStream)
            {
                MimeType objMimeType = null;
                if (objInputStream != null)
                {
                    var strMimeXMLPath = HttpContext.Current.Server.MapPath("~/mime-types.xml");
                    var g_MimeTypes = new MimeTypes(strMimeXMLPath);
                    sbyte[] sfileData = null;
                    byte[] objData = new byte[objInputStream.Length];
                    objInputStream.Read(objData, 0, (Int32)objInputStream.Length);
                    sfileData = Winista.Mime.SupportUtil.ToSByteArray(objData);
                    objMimeType = g_MimeTypes.GetMimeType(sfileData);
                    objInputStream.Close();
                    objInputStream.Dispose();
                }

                return objMimeType;
            }


    Friday, February 26, 2010 4:11 PM
  • User2040435453 posted

    I had the same problem. The cause is r.Close in the Finally block. This closes the HttpPostedFile in the calling code. Comment out r.Close and your code will work.

    Monday, March 5, 2012 12:02 PM