Link to home
Start Free TrialLog in
Avatar of tia_kamakshi
tia_kamakshiFlag for United Arab Emirates

asked on

Validating file type in file upload

Hi Experts,

I am working on ASP.net2.0 using C#

There is a functionality to upload files. I wanted to validate if user uploads file, then file should be valid type.

I need to validate for MP3 files, If user rename the MP3 file to say with .txt file, user should get an error, that file is not valid type

Please help me how to do this

Regards,
Avatar of BuggyCoder
BuggyCoder
Flag of India image

Avatar of Chinmay Patel
Hi tia_kamakshi,

If you are trying to determine by just checking the extesnion, you could do it on clientside itself via JavaScripe.
http://www.codeproject.com/Articles/156981/Check-File-type-at-client-side-jQuery

If you want to do it at server side [but file is uploaded anyways] by just looking at the extensino then
http://stackoverflow.com/questions/5125894/get-file-type-of-request-files-in-asp-net

Let me know if you need more help.

Regards,
Chinmay.
Avatar of tia_kamakshi

ASKER

Thanks for all your replies.

I am already validating by file extensions. I meant in my orignal question that

"I need to validate for MP3 files, If user rename the MP3 file to say with .txt file, user should get an error, that file is not valid type"

If user rename the file and makes that to txt file, then above solutions will allow user to upload the file.

Here user has uploaded the MP3 file by renaming it to .txt file, I need to validate if file is actual txt file and not MP3.

Our Security department will not pass by validating file using file extensions only. I need only valid files to be uploaded, user should not be able to do any ir-relevant things

Regards,
Hi tia_kamakshi,

I have a question here. The file that is being uploaded is always going to be a text file?

Regards,
Chinmay.
you basically have to check the type of file by reading its first few bytes.

Here are the links that will help you achieve this:-
http://stackoverflow.com/questions/2921646/programatically-find-out-a-file-type-by-looking-its-binary-content-possible
http://www.wotsit.org/
BuggyCoder
Your both links are not good examples. Not sure if you understood my question well.

Chinmay_Patel
User can upload few file types for example .txt, pdf, .doc, .docx, .xls, .xlsx

We might have to check file mime type etc to solve this. We have a solution for .exe file, if user rename .exe with any file extension say txt, then my code recognise that whether it is really txt or not

But we are not able to fix for .Mp3 file. I have not seen the code yet how .exe things has fixed. The guy working on this has gone for emergency leave and I have to fix this for .mp3 file

Regards,
Unfortunately, BuggyCoder's links are exactly what you have to do. Think about it:  does Office check a mime type when it opens a file? No. It looks for the "magic number" (referenced in the previously mentioned links) to tell if the file is a valid file to be opened. The only way to tell that a submitted file is of the type as indicated by the client is to examine the file in the same way that the associated program would. Mime type is not that way.
ohh I understand. How do we check this in ASP.net 2.0 using C#.

Also , I am checking following mime types only, then why it is failing in case of mp3 file. I mean if mp3 file extension is renamed (say .txt) then it is not recognising and accepting the file. But when I rename to .exe or some other then it recognise that it is not valid file type


application/msword
application/vnd.ms-word
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/pdf
application/excel
application/x-excel
application/x-msexcel
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/plain
text/plain
text/html
application/powerpoint
application/mspowerpoint
application/vnd.ms-powerpoint
application/x-mspowerpoint
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/rtf
application/x-rtf
text/richtext
text/rtf
image/bmp
image/x-windows-bmp
image/jpeg
image/pjpeg
image/gif

Please suggest

Regards,
Mime type check is applied by the server looking at the content-type header, so whatever you set in there it will work....
you have to literally scan the first few bytes, the byte array to scan can be found as given below:-

// Get a reference to PostedFile object
HttpPostedFile myFile = filMyFile.PostedFile;

// Get size of uploaded file
int nFileLen = myFile.ContentLength;

// Allocate a buffer for reading of the file
byte[] myData = new byte[nFileLen];

// Read uploaded file from the Stream
myFile.InputStream.Read(myData, 0, nFileLen);

Open in new window


you have to scan the first few bytes of myData to see if it is a mp3 file, if not discard the same and send a failure message back to the client....
Source: http://www.codeproject.com/Articles/1757/File-Upload-with-ASP-NET
Hi,

Thanks for your replies

In my application user should be able to upload pdf, doc, xls, images etc

How will below code recognise whether file is image file, excel file, pdf file, text file, rtf file etc.,

// Get a reference to PostedFile object
HttpPostedFile myFile = filMyFile.PostedFile;

// Get size of uploaded file
int nFileLen = myFile.ContentLength;

// Allocate a buffer for reading of the file
byte[] myData = new byte[nFileLen];

// Read uploaded file from the Stream
myFile.InputStream.Read(myData, 0, nFileLen);


How will this distinguish the actual file type.

line below
myFile.InputStream.Read(myData, 0, nFileLen);

will read any file in bytes.

Even the links provided is not validating file type at server side

"^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.mp3|.MP3|.mpeg|.MPEG|.m3u|.M3U)$"

but it is validating file type by its file extensions by regular expression.

This is not my requirement

Please suggest

Thanks again
I have gone through the articles and I realise the way you suggested is really the good way to implement.

At the same, I am finding hard to implement this in ASP.net using C#, as all above urls talks more about theory.

Please can you help me with code snippet in ASP.net using C#, that will help me more.

Regards,
Read the first few bytes as suggested by the urls for your types:-

           
var bArray = new byte[] {10, 20, 15, 19, 17, 19};
            var mp3Array = new byte[] {10, 20, 15, 19};

            var myArray = bArray.Take(4).ToArray();

            if(myArray.SequenceEqual(mp3Array))
            {
                Console.Write("MP3 file");
            }
            else
            {
                Console.WriteLine("Not An Mp3 Array");
            }

Open in new window


I hope you are able to convert the hexadecimal to byte array to have your byte arrays for your file types....
You can use Regular expression validator

<asp:RegularExpressionValidator id=”RegularExpressionValidator1"  runat=”server”
ErrorMessage=”Only mp3 file is allowed!”  ValidationExpression =”^.+(.mp3|.MP3)$”
ControlToValidate=”FileUpload1" > </asp:RegularExpressionValidator>

Open in new window

anuradhay
Thanks for your reply but I am not looking solution to get file type using file extensions.

BuggyCoder
Thanks for your reply. This looks fantastic.
At the same looks I am not at your level, you looks much more than me.

I am not able to convert the hexadecimal to byte array to have your byte arrays for your file types


var mp3Array = new byte[] {10, 20, 15, 19};

I am working on ASP.Net2.0, there var will not work. What should I write in place of var here

You want me to do something like this:

.ASPX Code
<input id="filMyFile" type="file" runat="server">

.CS file code
HttpPostedFile myFile = filMyFile.PostedFile;

int nFileLen = myFile.ContentLength;

byte[] bArray = new byte[nFileLen];


var mp3Array = new byte[] {10, 20, 15, 19};
var pdfArray = new byte[] {How do I get this};
var docArray = new byte[] {How do I get this};
var docxArray = new byte[] {How do I get this};
var jpegArray = new byte[] {How do I get this};
var gifArray = new byte[] {How do I get this};
var pngArray = new byte[] {How do I get this};
var xlsArray = new byte[] {How do I get this};
var xlsxArray = new byte[] {How do I get this};

var myArray = bArray.Take(4).ToArray();

if(myArray.SequenceEqual(mp3Array))
{
      Console.Write("MP3 file");
}
else if(myArray.SequenceEqual(pdfArray))
{
      Console.Write("PDF file");
}else if(myArray.SequenceEqual(docArray))
{
      Console.Write("DOC file");
}else if(myArray.SequenceEqual(docxArray))
{
      Console.Write("DOCX file");
}else if(myArray.SequenceEqual(jpegArray))
{
      Console.Write("JPEG file");
}else if(myArray.SequenceEqual(gifArray))
{
      Console.Write("GIF file");
}else if(myArray.SequenceEqual(xlsArray))
{
      Console.Write("XLS file");
}else if(myArray.SequenceEqual(xlsxArray))
{
      Console.Write("XLSX file");
}else
{
      Console.WriteLine("Unknown file type");
}


----------------------------------------------

----------------------------------------------------
application/msword
application/vnd.ms-word
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/pdf
application/excel
application/x-excel
application/x-msexcel
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/plain
text/plain
text/html
application/powerpoint
application/mspowerpoint
application/vnd.ms-powerpoint
application/x-mspowerpoint
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/rtf
application/x-rtf
text/richtext
text/rtf
image/bmp
image/x-windows-bmp
image/jpeg
image/pjpeg
image/gif
----------------------------------------------------

I need to make the filetype configurable in my configuration file as well.

Please suggest

Best Regards,
Here is a sample for you, by far the largest sample that i have ever shared on EE:-

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace EE_Console
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            //Using This code to read from file on my machine, 
            //you can replace this code with your custom
            //code to read file that is uploaded
            var pArr = File.ReadAllBytes(@"F:\Downloads\EIA100135_Receipt.pdf");
                
            //Create Instance Of Type Validator
            TypeValidator validator=new TypeValidator();

            //Lets Validate If It Is A Pdf File Or Not
            bool isValid = validator.Validate(FileType.Pdf, pArr);

            Console.Read();
        }
    }

    /// <summary>
    /// Enum to hold file types
    /// </summary>
    enum FileType
    {
        Mp3,
        Pdf
        //Create other types here...
    }

    /// <summary>
    /// Validates The File Type By Checking the File's Byte Array With Existing Signatures
    /// for each file type.
    /// </summary>
    class TypeValidator
    {
        private readonly Dictionary<FileType, byte[]> _dicTypes;

        /// <summary>
        /// Class To Hold Various File Signatures
        /// </summary>
        internal class Signatures
        {
            public const string Pdf = "25 50 44 46";
            public const string Mp3 = "49 44 33";
            //Add other type signatures here
        }

        public TypeValidator()
        {
            _dicTypes = new Dictionary<FileType, byte[]>();
            Initialize();
        }

        private void Initialize()
        {
            _dicTypes.Add(FileType.Pdf, HexToBytes(Signatures.Pdf));
            _dicTypes.Add(FileType.Mp3, HexToBytes(Signatures.Mp3));

            //Initialize other types here...
        }

        public bool Validate(FileType type, byte[] bytes)
        {
            if(!_dicTypes.ContainsKey(type)) return false;
            
            byte[] fileSig = _dicTypes[type];

            return
                bytes
                    .Take(fileSig.Length)
                    .SequenceEqual(fileSig);
        }

        private static byte[] HexToBytes(string hexNumber)
        {
            List<byte> bytes = new List<byte>();
            foreach(string str in hexNumber.Split(' '))
            {
                int number = Convert.ToInt32(str, 16);
                byte bite = Convert.ToByte(number);

                bytes.Add(bite);
            }

            return bytes.ToArray();
        }
    }
}

Open in new window


you can use this link to get signatures about other file types:-
http://www.garykessler.net/library/file_sigs.html

Happy Programming
:-)
I really thanks for your help you did.

public bool Validate(FileType type, byte[] bytes)
    {
        if (!_dicTypes.ContainsKey(type)) return false;

        byte[] fileSig = _dicTypes[type];

        return
            bytes            
                .Take(fileSig.Length)
                .SequenceEqual(fileSig);
    }


In Asp.net 2.0 it is giving error on line
.Take(fileSig.Length)

Error saying

Error      1      'System.Array' does not contain a definition for 'Take'      D:\Workspace\RandD\XMLXslt\Website\App_Code\TypeValidator.cs


Please can you help me in fixing this return type

return
            bytes            
                .Take(fileSig.Length)
                .SequenceEqual(fileSig);
               
How do we do this in ASP.net 2.0 using C#

I have never worked on above versions of ASP.net 2.0 and this type of return does not help in ASP.net2.0

and actually what these 2 lines are doing.

It would be great if you help me in understanding this as well

Best regards for your great help
public bool Validate(FileType type, byte[] bytes)
        {
            if(!_dicTypes.ContainsKey(type)) return false;
           
            byte[] fileSig = _dicTypes[type];
            byte[] newArr = new byte[fileSig.Length];

            Array.Copy(bytes, newArr, newArr.Length);
            return newArr.SequenceEqual(fileSig);
        }
Thanks for this.

Now I am getting the error below

Error      1      'System.Array' does not contain a definition for 'SequenceEqual'      

Please help me in fixing this

Regards,
ASKER CERTIFIED SOLUTION
Avatar of BuggyCoder
BuggyCoder
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Big Big Thanks to you for your great help