Zack Peterson
Zack Peterson

Reputation: 57323

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

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?

Upvotes: 14

Views: 52511

Answers (7)

Green Fire
Green Fire

Reputation: 709

You can use This list, that contains 684 file extensions.

In this list every pair is separated by "~", and every pair has the extension name and the content type separated by "#".

I dont know what language are you using but this is in vb.net

How to use it:

  1. Add a string resource to you project that contains the list. It will look like this - enter image description here
  2. Add this class to your project (that will parse the string to Dictionary)

    Public Class MIMETypeList
        Public data As Dictionary(Of String, String)
        Public Sub New()
           data = New Dictionary(Of String, String)()
           Dim Temp() As String
           For Each TypeConvertion As String In My.Resources.MimeType.Split("~")
               Temp = TypeConvertion.Split("#")
               If Not data.ContainsKey(Temp(0)) Then
                   data.Add(Temp(0), Temp(1))
               End If
           Next
        End Sub
    End Class
    
  3. Now you can use it like this:

    Dim FileExtension1 As String = ".mp4"
    Dim FileExtension2 As String = ".html"
    Dim FileExtension3 As String = ".Random"
    Dim Converter As New MIMETypeList
    If Converter.data.ContainsKey(FileExtension1) Then
        Debug.WriteLine(FileExtension1 & " -> " & Converter.data.Item(FileExtension1))
    Else
        Debug.WriteLine(FileExtension1 & " -> File Content Not Found")
    End If
    If Converter.data.ContainsKey(FileExtension2) Then
        Debug.WriteLine(FileExtension2 & " -> " & Converter.data.Item(FileExtension2))
    Else
        Debug.WriteLine(FileExtension2 & " -> File Content Not Found")
    End If
    If Converter.data.ContainsKey(FileExtension3) Then
        Debug.WriteLine(FileExtension3 & " -> " & Converter.data.Item(FileExtension3))
    Else
        Debug.WriteLine(FileExtension3 & " -> File Content Not Found")
    End If
    

    Output:

    .mp4 -> video/mp4

    .html -> text/html

    .Random -> File Content Not Found

Upvotes: 0

MrDebnath
MrDebnath

Reputation: 111

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!!!!

Upvotes: 4

jones6
jones6

Reputation: 784

There is a MimeMapping class in .NET 4.5

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

Upvotes: 22

Andre Pena
Andre Pena

Reputation: 59336

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.

Upvotes: 9

user1228
user1228

Reputation:

I use a custom config section in web.config (I leave the task for writing the custom configuration section to you):

<configSections>
    <section name="mimeTypeMappings" type="MySoftwareLol.MimeTypeMappingSection, MySoftwareLol"/>
</configSections>

<mimeTypeMappings>
    <MimeTypes>
      <MimeType Type="application/mac-binhex40" Extensions=".hqx"/>
      <MimeType Type="application/msword" Extensions=".doc"/>
      <MimeType Type="application/pdf" Extensions=".pdf"/>
      <MimeType Type="application/postscript" Extensions=".ai;.eps;.ps"/>
      <MimeType Type="application/rtf" Extensions=".rtf"/>
      <MimeType Type="application/vnd.ms-excel" Extensions=".xla;.xlc;.xlm;.xls;.xlt;.xlw"/>
      <MimeType Type="application/vnd.ms-outlook" Extensions=".msg"/>
      <MimeType Type="application/vnd.ms-powerpoint" Extensions=".pot;.pps;.ppt"/>
      <MimeType Type="application/vnd.ms-works" Extensions=".wcm;.wdb;.wks;.wps"/>
      <MimeType Type="application/x-compress" Extensions=".z"/>
      <MimeType Type="application/x-compressed" Extensions=".tgz"/>
      <MimeType Type="application/x-gzip" Extensions=".gz"/>
      <MimeType Type="application/x-msaccess" Extensions=".mdb"/>
      <MimeType Type="application/x-msmetafile" Extensions=".wmf"/>
      <MimeType Type="application/x-mspublisher" Extensions=".pub"/>
      <MimeType Type="application/x-msschedule" Extensions=".scd"/>
      <MimeType Type="application/x-msterminal" Extensions=".trm"/>
      <MimeType Type="application/x-mswrite" Extensions=".wri"/>
      <MimeType Type="application/x-tar" Extensions=".tar"/>
      <MimeType Type="application/zip" Extensions=".zip"/>
      <MimeType Type="audio/basic" Extensions=".au;.snd"/>
      <MimeType Type="audio/mid" Extensions=".mid;.rmi"/>
      <MimeType Type="audio/mpeg" Extensions=".mp3"/>
      <MimeType Type="audio/x-aiff" Extensions=".aif;.aifc;.aiff"/>
      <MimeType Type="audio/x-pn-realaudio" Extensions=".ra;.ram"/>
      <MimeType Type="audio/x-wav" Extensions=".wav"/>
      <MimeType Type="image/bmp" Extensions=".bmp"/>
      <MimeType Type="image/gif" Extensions=".gif"/>
      <MimeType Type="image/jpeg" Extensions=".jpe;.jpeg;.jpg"/>
      <MimeType Type="image/pipeg" Extensions=".jfif"/>
      <MimeType Type="image/tiff" Extensions=".tif;.tiff"/>
      <!--By default, sends HTML documents as plain text; sending it as text/html may pose security risks-->
      <!--If you wish to accept the risks, uncomment the following two lines and comment out the third.-->
      <!--<MimeType Type="text/html" Extensions=".mht;.html;.htm"/>-->
      <!--<MimeType Type="text/plain" Extensions=".txt"/>-->
      <MimeType Type="text/plain" Extensions=".txt;.html;.htm"/>
      <MimeType Type="text/richtext" Extensions=".rtx"/>
      <MimeType Type="text/tab-separated-values" Extensions=".tsv"/>
      <MimeType Type="video/mpeg" Extensions=".mp2;.mpa;.mpe;.mpeg;.mpg;.mpv2"/>
      <MimeType Type="video/quicktime" Extensions=".mov;.qt"/>
      <MimeType Type="video/x-la-asf" Extensions=".lsf;.lsx;.asf;.asr;.asx;"/>
      <MimeType Type="video/x-msvideo" Extensions=".avi"/>
    </MimeTypes>
  </mimeTypeMappings>

I use Path.GetExtension() and map that to one of the types listed in Extensions.

Upvotes: 4

Zack Peterson
Zack Peterson

Reputation: 57323

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.

Upvotes: 15

CodingWithSpike
CodingWithSpike

Reputation: 43698

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

Upvotes: 2

Related Questions