Getting a mime type based on a file name (Or file extension), is one of those weird things you never really think about until you really, really need it. I recently ran into the issue when trying to return a file from an API (Probably not the best practice, but I had to make it happen), and I wanted to specify the mime type to the caller. I was amazed with how things “used” to be done both in the .NET Framework, and people’s answers on Stack Overflow.

How We Used To Work Out The Mime Type Based On a File Name (aka The Old Way)

If you were using the .NET Framework, you had two ways to get going. Now I know this is a .NET Core blog, but I still found it interesting to see how we got to where we are now.

The first way is that you build up a huge dictionary yourself of mappings between file extensions and mime types. This actually isn’t a bad way of doing things if you only expect a few different types of files need to be mapped.

The second was that in the System.Web namespace of the .NET Framework there is a static class for mapping classes. We can actually see the source code for this mapping here : https://referencesource.microsoft.com/#system.web/MimeMapping.cs. If you were expecting some sort of mime mapping magic to be happening well, just check out this code snippet.

 
1
2
3
4
5
6
7
8
9
10
11
12
private sealed class MimeMappingDictionaryClassic : MimeMappingDictionaryBase {
protected override void PopulateMappings() {
// This list was copied from the IIS7 configuration file located at:
// %windir%\system32\inetsrv\config\applicationHost.config
 
AddMapping(".323", "text/h323");
AddMapping(".aaf", "application/octet-stream");
AddMapping(".aca", "application/octet-stream");
AddMapping(".accdb", "application/msaccess");
[...]
}
}

400+ lines of manual mappings that were copied and pasted from the default IIS7 list. So, not that great.

But the main issue with all of this is that it’s too hard (close to impossible) to add and remove custom mappings. So if your file extension isn’t in the list, you are out of luck.

The .NET Core Way

.NET Core obviously has it’s own way of doing things that may seem a bit more complicated but does work well.

First, we need to install the following nuget package :

 
1
Install-Package Microsoft.AspNetCore.StaticFiles

Annoyingly the class we want to use lives inside this static files nuget package. I would say if that becomes an issue for you, to look at the source code and make it work for you in whatever way you need. But for now, let’s use the package.

Now we have access to a nifty little class called FileExtensionContentTypeProvider . Here’s some example code using it. I’ve created a simple API action that takes a filename, and returns the mime type :

 
1
2
3
4
5
6
7
8
9
10
11
[HttpGet]
public string Get(string fileName)
{
    var provider = new FileExtensionContentTypeProvider();
    string contentType;
    if(!provider.TryGetContentType(fileName, out contentType))
    {
        contentType = "application/octet-stream";
    }
    return contentType;
}

Nothing too crazy and it works! We also catch if it doesn’t manage to map it, and just map it ourselves to a default content type. This is one thing that the .NET Framework MimeMapping class did have, was that if it couldn’t find the correct mapping, it returned application/octet-stream. But I can see how this is far more definitive as to what’s going on.

But here’s the thing, if we look at the source code of this here, we can see we are no better off in terms of doing things by “magic”, it’s still one big dictionary under the hood. And the really interesting part? We can actually add our own mappings! Let’s modify our code a bit :

 
1
2
3
4
5
6
7
8
9
10
11
12
[HttpGet]
public string Get(string fileName)
{
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings.Add(".dnct", "application/dotnetcoretutorials");
    string contentType;
    if(!provider.TryGetContentType(fileName, out contentType))
    {
        contentType = "application/octet-stream";
    }
    return contentType;
}

I’ve gone mad with power and created a new file extension called .dnct and mapped it to it’s own mimetype. Everything is a cinch!

But our last problem. What if we want to use this in multiple places? What if we need better control for unit testing that “instantiating” everytime won’t really give us? Let’s create a nice mime type mapping service!

We could create this static, but then we lose a little flexibility around unit testing. So I’m going to create an interface too. Our service looks like so :

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface IMimeMappingService
{
    string Map(string fileName);
}
 
public class MimeMappingService : IMimeMappingService
{
    private readonly FileExtensionContentTypeProvider _contentTypeProvider;
 
    public MimeMappingService(FileExtensionContentTypeProvider contentTypeProvider)
    {
        _contentTypeProvider = contentTypeProvider;
    }
 
    public string Map(string fileName)
    {
        string contentType;
        if (!_contentTypeProvider.TryGetContentType(fileName, out contentType))
        {
            contentType = "application/octet-stream";
        }
        return contentType;
    }
}

So we provide a single method called “Map”. And when creating our MimeMappingService, we take in a content service provider.

Now we need to head to our startup.cs and in our ConfigureServices method we need to wire up the service. That looks a bit like this :

 
1
2
3
4
5
6
7
8
public void ConfigureServices(IServiceCollection services)
{
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings.Add(".dnct", "application/dotnetcoretutorials");
    services.AddSingleton<IMimeMappingService>(new MimeMappingService(provider));
 
    services.AddMvc();
}

So we instantiate our FileExtensionContentTypeProvider, give it our extra mappings, then bind our MimeMappingService all up so it can be injected.

In our controller we change out code to look a bit like this :

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ValuesController : Controller
{
    private readonly IMimeMappingService _mimeMappingService;
 
    public ValuesController(IMimeMappingService mimeMappingService)
    {
        _mimeMappingService = mimeMappingService;
    }
 
    [HttpGet]
    public string Get(string fileName)
    {
        return _mimeMappingService.Map(fileName);
    }
}

Nice and clean. And it means that any time we inject our MimeMappingService around, it has all our customer mappings contained within it!

.NET Core Static Files

There is one extra little piece of info I should really give out too. And that is if you are using the .NET Core static files middleware to serve raw files, you can also use this provider to return the correct mime type. So for example you can do things like this :

 
1
2
3
4
5
6
7
8
9
10
11
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
 
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings.Add(".dnct", "application/dotnetcoretutorials");
 
    app.UseStaticFiles(new StaticFileOptions
    {
        ContentTypeProvider = provider
    });
}

So now when outside of C# code, and we are just serving the raw file of type .dnct, we will still return the correct MimeType.

Getting A Mime Type From A File Name In .NET Core的更多相关文章

  1. File upload - MIME type

    Your goal is to hack this photo galery by uploading PHP code.Retrieve the validation password in the ...

  2. solr异常--Expected mime type application/octet-stream but got text/html.

    Exception in thread "main" org.apache.solr.client.solrj.impl.HttpSolrServer$RemoteSolrExce ...

  3. nginx: [warn] duplicate MIME type "text/html"错误

    检查配置文件时提示:nginx: [warn] duplicate MIME type "text/html" in /home/web/nginx/inc/gzip.conf:9 ...

  4. php 获取 mime type 类型,fileinfo扩展

    背景: version < php-5.3 没有API能够查看文件的 mime_type, 故需要编译扩展 fileinfo 来扩展PHP的API(finfo_*系列函数).php-5.3 以后 ...

  5. [笔记] C# 如何获取文件的 MIME Type

    MIME Type 为何物: MIME 参考手册 svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types 常规方式 对于有文件后 ...

  6. Unable to guess the mime type as no guessers are available 2 9

    做了一个上传图片的功能,在本地上传通过,服务器报 bug Unable to guess the mime type as no guessers are available(Did you enab ...

  7. MIME Type

    一.首先,我们要了解浏览器是如何处理内容的.在浏览器中显示的内容有 HTML.有 XML.有 GIF.还有 Flash --那么,浏览器是如何区分它们,决定什么内容用什么形式来显示呢?答案是 MIME ...

  8. Chrome: Resource interpreted as Font but transferred with MIME type font/x-woff

    最近,项目中加入了Bootstrap进行界面优化,但是,项目加载运行之后,控制台总是提示以下错误信息: GET http://localhost:8080/.../fonts/fontawesome- ...

  9. Resource interpreted as Script but transferred with MIME type text/plain:

    我用script做ajax跨域,请求返回的是个文本字符串,chrome提示:Resource interpreted as Script but transferred with MIME type ...

随机推荐

  1. qbittorrent搜索插件合集

    qbittorrent搜索 qbittorrent搜索一个很有特色的功能: 这里收集整理了一些公开网站的插件(Plugins for Public sites),并连 源py文件一起分享. qbitt ...

  2. c++打印实心菱形,空心三角形,十字星,空心正方形,实心平行四边形

    今天翻资料的时候,无意间发现了一个文件,是刚接触编程的时候用c++写的一段程序,我称之为"图形打印机",想着把所有图形都打印出来,后来发现其实每种图形的代码都是一个思路,就不想做重 ...

  3. JQuery EasyUI Tree组件的Bug记录

    记录一下使用项目中使用EasyUI遇到的bug,废话少说直接上菜  - _-(bug)..... bug ::   .netcore创建一个web应用时候,会自动引入jQuery库以及一些插件,但是在 ...

  4. (原创)使用C#开发PLC上位机监控系统客户端应用程序

    PLC客户端监控系统的特点: 0.客户端系统软件可部署在 多个管理层的PC机上,或者需要部署在距离服务器较远区域的PC机上,通过网线连接到服务器端的交换机. 1应用范围: (1)所有客户端都只有监视功 ...

  5. altermanager使用报错

    报错如下: level=warn ts=2019-01-24T09:20:01.122920737Z caller=cluster.go:148 component=cluster err=" ...

  6. python中字典的建立

    一.字典由键key与值value构成. 如: a={'d':6,'f':'va'}print(a['f']) 上面代码简单建立字典,其中需要访问字典需要输入键值. 二.又比如需要在某个关键字中添加数据 ...

  7. 为什么要用 redis 而不用 map 做缓存?

    缓存分为本地缓存和分布式缓存.以 Java 为例,使用自带的 map 或者 guava 实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着 jvm 的销毁而结束,并且在多实例的情况下,每个实例 ...

  8. Springboot揭秘-快速构建微服务体系-王福强-2016年5月第一次印刷

    JavaConfig项目: spring IOC有一个非常核心的概念——Bean.由Spring容器来负责对Bean的实例化,装配和管理.XML是用来描述Bean最为流行的配置方式.Spring可以从 ...

  9. 事件绑定+call apply指向

    JS高级 事件—— 浏览器客户端上客户触发的行为都称为事件 所有事件都是天生自带的,不需要我们去绑定,只需要我们去触发,通过obj.事件名=function(){ } 事件名:onmousemove: ...

  10. SqlServer共用表达式(CTE)With As 处理递归查询

    共用表表达式(CTE)可以看成是一个临时的结果集,可以再SELECT,INSERT,UPDATE,DELETE,MARGE语句中多次引用. 一好处:使用共用表表达式可以让语句更加清晰简练. 1.可以定 ...