How do I determine a file's content type in .NET?

46,543

Solution 1

I've replaced the FileExtension column in my database table with a ContentType column.

I populate it when I upload a file.

Private Sub ButtonUpload_Click(...)
    ...
    Dim FileExtension As String = "." + FileBox.FileName.Split(".").Last.ToLower
    z.ContentType = ContentType(FileExtension)
    ...
End Sub

I determine the content type with this function:

Function ContentType(ByVal FileExtension As String) As String
    Dim d As New Dictionary(Of String, String)
    'Images'
    d.Add(".bmp", "image/bmp")
    d.Add(".gif", "image/gif")
    d.Add(".jpeg", "image/jpeg")
    d.Add(".jpg", "image/jpeg")
    d.Add(".png", "image/png")
    d.Add(".tif", "image/tiff")
    d.Add(".tiff", "image/tiff")
    'Documents'
    d.Add(".doc", "application/msword")
    d.Add(".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
    d.Add(".pdf", "application/pdf")
    'Slideshows'
    d.Add(".ppt", "application/vnd.ms-powerpoint")
    d.Add(".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation")
    'Data'
    d.Add(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    d.Add(".xls", "application/vnd.ms-excel")
    d.Add(".csv", "text/csv")
    d.Add(".xml", "text/xml")
    d.Add(".txt", "text/plain")
    'Compressed Folders'
    d.Add(".zip", "application/zip")
    'Audio'
    d.Add(".ogg", "application/ogg")
    d.Add(".mp3", "audio/mpeg")
    d.Add(".wma", "audio/x-ms-wma")
    d.Add(".wav", "audio/x-wav")
    'Video'
    d.Add(".wmv", "audio/x-ms-wmv")
    d.Add(".swf", "application/x-shockwave-flash")
    d.Add(".avi", "video/avi")
    d.Add(".mp4", "video/mp4")
    d.Add(".mpeg", "video/mpeg")
    d.Add(".mpg", "video/mpeg")
    d.Add(".qt", "video/quicktime")
    Return d(FileExtension)
End Function

This works, but it seems inelegant.

Solution 2

There is a MimeMapping class in .NET 4.5

http://msdn.microsoft.com/en-us/library/system.web.mimemapping.aspx

Solution 3

I made a C# helper class based on Zacks response.

/// <summary>
/// Helps with Mime Types
/// </summary>
public static class MimeTypesHelper
{
    /// <summary>
    /// Returns the content type based on the given file extension
    /// </summary>
    public static string GetContentType(string fileExtension)
    {
        var mimeTypes = new Dictionary<String, String>
            {
                {".bmp", "image/bmp"},
                {".gif", "image/gif"},
                {".jpeg", "image/jpeg"},
                {".jpg", "image/jpeg"},
                {".png", "image/png"},
                {".tif", "image/tiff"},
                {".tiff", "image/tiff"},
                {".doc", "application/msword"},
                {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
                {".pdf", "application/pdf"},
                {".ppt", "application/vnd.ms-powerpoint"},
                {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
                {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
                {".xls", "application/vnd.ms-excel"},
                {".csv", "text/csv"},
                {".xml", "text/xml"},
                {".txt", "text/plain"},
                {".zip", "application/zip"},
                {".ogg", "application/ogg"},
                {".mp3", "audio/mpeg"},
                {".wma", "audio/x-ms-wma"},
                {".wav", "audio/x-wav"},
                {".wmv", "audio/x-ms-wmv"},
                {".swf", "application/x-shockwave-flash"},
                {".avi", "video/avi"},
                {".mp4", "video/mp4"},
                {".mpeg", "video/mpeg"},
                {".mpg", "video/mpeg"},
                {".qt", "video/quicktime"}
            };

        // if the file type is not recognized, return "application/octet-stream" so the browser will simply download it
        return mimeTypes.ContainsKey(fileExtension) ? mimeTypes[fileExtension] : "application/octet-stream";
    }
}

You might, of course, want to keep the mimeTypes alive for future queries. This is just a starting point.

Solution 4

can be easily done by using registry keys.

Dim regKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("extension")
If Not regKey Is Nothing Then
Dim ct As Object = regKey.GetValue("Content Type")
  If Not ct Is Nothing Then
     Return ct.ToString()
  End If
End If

This will produce the same result as the big list mentioned above!!!!

Solution 5

It looks like you still have the filename when you go to set the content type. You could pick the correct mime type for the file extension, or default to something like "application/base64".

Assuming the person downloading it will be using a web browser, try to stick to the common ones: MIME Types Known By IE

Share:
46,543
Zack Peterson
Author by

Zack Peterson

Specializes in the design and creation of web and desktop applications. Contributes in all aspects of the software development process such as: requirements analysis and product definition; prototyping; choosing architecture and framework; interface design; database design; installation and integration; documentation and training; gathering feedback; and maintenance.

Updated on July 09, 2022

Comments

  • Zack Peterson
    Zack Peterson almost 2 years

    My WPF application gets a file from the user with Microsoft.Win32.OpenFileDialog()...

    Private Sub ButtonUpload_Click(...)
        Dim FileOpenStream As Stream = Nothing
        Dim FileBox As New Microsoft.Win32.OpenFileDialog()
        FileBox.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
        FileBox.Filter = "Pictures (*.jpg;*.jpeg;*.gif;*.png)|*.jpg;*.jpeg;*.gif;*.png|" & _
                         "Documents (*.pdf;*.doc;*.docx;)|*.pdf;*.doc;*.docx;|" & _
                         "All Files (*.*)|*.*"
        FileBox.FilterIndex = 1
        FileBox.Multiselect = False
        Dim FileSelected As Nullable(Of Boolean) = FileBox.ShowDialog(Me)
        If FileSelected IsNot Nothing AndAlso FileSelected.Value = True Then
            Try
                FileOpenStream = FileBox.OpenFile()
                If (FileOpenStream IsNot Nothing) Then
                    Dim ByteArray As Byte()
                    Using br As New BinaryReader(FileOpenStream)
                        ByteArray = br.ReadBytes(FileOpenStream.Length)
                    End Using
                    Dim z As New ZackFile
                    z.Id = Guid.NewGuid
                    z.FileData = ByteArray
                    z.FileSize = CInt(ByteArray.Length)
                    z.FileName = FileBox.FileName.Split("\").Last
                    z.DateAdded = Now
                    db.AddToZackFile(z)
                    db.SaveChanges()
                End If
            Catch Ex As Exception
                MessageBox.Show("Cannot read file from disk. " & Ex.Message, "Fail", MessageBoxButton.OK, MessageBoxImage.Error)
            Finally
                If (FileOpenStream IsNot Nothing) Then
                    FileOpenStream.Close()
                End If
            End Try
        End If
    End Sub
    

    And my ASP.NET MVC application serves it up for download at a web site with FileStreamResult()...

    Public Class ZackFileController
        Inherits System.Web.Mvc.Controller
    
        Function Display(ByVal id As Guid) As FileStreamResult
            Dim db As New EfrDotOrgEntities
            Dim Model As ZackFile = (From z As ZackFile In db.ZackFile _
                                    Where z.Id = id _
                                    Select z).First
            Dim ByteArray As Byte() = Model.ImageData
            Dim FileStream As System.IO.MemoryStream = New System.IO.MemoryStream(ByteArray)
            Dim ContentType As String = ?????
            Dim f As New FileStreamResult(FileStream, ContentType)
            f.FileDownloadName = Model.FileName
            Return f
        End Function
    
    End Class
    

    But FileStreamResult() needs a content type string. How do I know the correct content type of my file?

  • StriplingWarrior
    StriplingWarrior over 12 years
    You probably ought to use a switch statement rather than building a new dictionary every time you call ContentType. Also, there's a Path.GetExtension method so you don't have to split the file name manually.
  • user1601201
    user1601201 over 12 years
    VB.Net 10 is a little nicer... Dim d As New Dictionary(Of String, String) From { {".bmp", "image/bmp"}, {".gif", "image/gif"}, {".jpeg", "image/jpeg"}} 'etc
  • Ivaylo Slavov
    Ivaylo Slavov over 11 years
    @StriplingWarrior, or keep a single static dictionary. If the method is frequently used and supports that much of file extensions, I think it will be speed things up a little
  • StriplingWarrior
    StriplingWarrior over 11 years
    @IvayloSlavov: A dictionary may be a good idea, especially if you want the list of supported extensions to be dynamic, or have it loaded in from a config file or something. But it won't be faster. The compiler is smart enough to implement a switch statement using a dictionary, or some other structure depending on how it thinks it will get better performance.
  • Ivaylo Slavov
    Ivaylo Slavov over 11 years
    @StriplingWarrior, yep, you've got a point on this, the compiler is able to do some white magic with the final code. Still, I'd choose a dictionary, because it will provide me with a little more flexibility than a switch statement, and I can fill it with external data, maybe coming from a configuration or database.
  • Asad Saeeduddin
    Asad Saeeduddin almost 11 years
    You can save quite a few characters by using d(".csv") = "text/csv" instead.
  • Liam Laverty
    Liam Laverty over 9 years
    This isn't reliable enough for anything that's going to go through pen testing. I could upload a .exe renamed to .docx using this example.
  • Green Fire
    Green Fire over 8 years
    This should be the answer.
  • interesting-name-here
    interesting-name-here about 7 years
    Brilliant, much better than me pulling information down and creating a MimeMapping table myself.
  • Ultroman the Tacoman
    Ultroman the Tacoman almost 7 years
    But...the MimeMapping class in .NET simply maps to the extension given in the filename string. It doesn't check the magic bytes.