How do I determine a file's content type in .NET?
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
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, 2022Comments
-
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 over 12 yearsYou probably ought to use a switch statement rather than building a new dictionary every time you call
ContentType
. Also, there's aPath.GetExtension
method so you don't have to split the file name manually. -
user1601201 over 12 yearsVB.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 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 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 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 almost 11 yearsYou can save quite a few characters by using
d(".csv") = "text/csv"
instead. -
Liam Laverty over 9 yearsThis 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 over 8 yearsThis should be the answer.
-
interesting-name-here about 7 yearsBrilliant, much better than me pulling information down and creating a MimeMapping table myself.
-
Ultroman the Tacoman almost 7 yearsBut...the MimeMapping class in .NET simply maps to the extension given in the filename string. It doesn't check the magic bytes.