crazyTechie
crazyTechie

Reputation: 2557

Check type of uploaded file

How do I check the file type of a file uploaded using FileUploader control in an ASP.NET C# webpage?

  1. I tried checking file extension, but it obviously fails when a JPEG image (e.g. Leonardo.jpg) is renamed to have a PDF's extension (e.g. Leonardo.pdf).

  2. I tried

    FileUpload1.PostedFile.ContentType.ToLower().Equals("application/pdf")
    

    but this fails as the above code behaves the same way as the first did.

Is there any other way to check the actual file type, not just the extension?

I looked at ASP.NET how to check type of the file type irrespective of extension.

Edit: I tried below code from one of the posts in stackoverflow. But this down't work. Any idea about this.

/// <summary>
/// This class allows access to the internal MimeMapping-Class in System.Web
/// </summary>
class MimeMappingWrapper
{
  static MethodInfo getMimeMappingMethod;

    static MimeMappingWrapper() {
    // dirty trick - Assembly.LoadWIthPartialName has been deprecated
    Assembly ass = Assembly.LoadWithPartialName("System.Web");
    Type t = ass.GetType("System.Web.MimeMapping");

    getMimeMappingMethod t.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public));
}

/// <summary>
/// Returns a MIME type depending on the passed files extension
/// </summary>
/// <param name="fileName">File to get a MIME type for</param>
/// <returns>MIME type according to the files extension</returns>
public static string GetMimeMapping(string fileName) {
    return (string)getMimeMappingMethod.Invoke(null, new[] { fileName });
}
}

Upvotes: 3

Views: 10959

Answers (3)

Jeremy Thompson
Jeremy Thompson

Reputation: 65712

Dont use File Extensions to work out MIME Types, instead use "Winista" for binary analysis.

Say someone renames an exe with a jpg extension. You can still determine the real file format. It doesn't detect swf's or flv's but does pretty much every other well known format and you can get a hex editor to add more files it can detect.

Download Winista: here or my mirror or my GitHub https://github.com/MeaningOfLights/MimeDetect.

Where Winista fails to detect the real file format, I've resorted back to the URLMon method:

public class urlmonMimeDetect
{
    [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
    private extern static System.UInt32 FindMimeFromData(
        System.UInt32 pBC,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
        [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
        System.UInt32 cbSize,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
        System.UInt32 dwMimeFlags,
        out System.UInt32 ppwzMimeOut,
        System.UInt32 dwReserverd
    );

public string GetMimeFromFile(string filename)
{
    if (!File.Exists(filename))
        throw new FileNotFoundException(filename + " not found");

    byte[] buffer = new byte[256];
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        if (fs.Length >= 256)
            fs.Read(buffer, 0, 256);
        else
            fs.Read(buffer, 0, (int)fs.Length);
    }
    try
    {
        System.UInt32 mimetype;
        FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
        System.IntPtr mimeTypePtr = new IntPtr(mimetype);
        string mime = Marshal.PtrToStringUni(mimeTypePtr);
        Marshal.FreeCoTaskMem(mimeTypePtr);
        return mime;
    }
    catch (Exception e)
    {
        return "unknown/unknown";
    }
}
}

From inside the Winista method, I fall back on the URLMon here:

   public MimeType GetMimeTypeFromFile(string filePath)
    {
        sbyte[] fileData = null;
        using (FileStream srcFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] data = new byte[srcFile.Length];
            srcFile.Read(data, 0, (Int32)srcFile.Length);
            fileData = Winista.Mime.SupportUtil.ToSByteArray(data);
        }

        MimeType oMimeType = GetMimeType(fileData);
        if (oMimeType != null) return oMimeType;

        //We haven't found the file using Magic (eg a text/plain file)
        //so instead use URLMon to try and get the files format
        Winista.MimeDetect.URLMONMimeDetect.urlmonMimeDetect urlmonMimeDetect = new Winista.MimeDetect.URLMONMimeDetect.urlmonMimeDetect();
        string urlmonMimeType = urlmonMimeDetect.GetMimeFromFile(filePath);
        if (!string.IsNullOrEmpty(urlmonMimeType))
        {
            foreach (MimeType mimeType in types)
            {
                if (mimeType.Name == urlmonMimeType)
                {
                    return mimeType;
                }
            }
        }

        return oMimeType;
    }

Update:

To work out more files using magic here is a FILE SIGNATURES TABLE

Upvotes: 6

Sajjad mc
Sajjad mc

Reputation: 75

you can check you file type in FileApload by

ValidationExpression="^.+.(([pP][dD][fF])|([jJ][pP][gG])|([pP][nN][gG])))$"

for ex: you can add ([rR][aA][rR]) for Rar file type and etc ...

Upvotes: -2

Murtuza Kabul
Murtuza Kabul

Reputation: 6524

Checking the names or extension is in no way a reliable idea. The only way you can be sure is that you actually read the content of the file.

i.e. if you want to check the file for image, you should try loading image from the file and if it fails, you can be sure that it is not an image file. This can be done easily using GDI objects.

Same is also true for PDF files.

Conclusion is, don't rely on the user supplied name or extension.

Upvotes: -1

Related Questions