Come ottenere il Content-Type / MIME Type dall’estensione di un file in ASP.NET C#

Come posso recuperare il MIME Type di un determinato file in C#? Si tratta di una domanda molto frequente tra sviluppatori e che mi capita di sentire spesso da amici e colleghi che lavorano sul framework ASP.NET per realizzare applicazioni MVC, Web API e (ultimamente) .NET Core. Il motivo è semplice: se si lavora di frequente con filesystem e database prima o poi arriva sempre la necessità di recuperare il MIME type di un file, ad esempio al momento di inviarlo al browser dell’utente al termine di una request. In tutti i casi in cui il MIME Type non è stato memorizzato in precedenza, non possiamo fare altro che recuperarlo basandoci sull’estensione del file in questione, che nella maggior parte dei casi fornisce un indizio inequivocabile per identificare la tipologia di file da inviare: abbiamo quindi bisogno di effettuare un mapping tra le varie possibili estensioni che possono avere i nostri file e il MIME Type corrispondente a ciascuna di esse.

Esistono numerose tecniche che consentono di svolgere questa operazione in modo più o meno efficiente. Per ragioni di semplicità ci limiteremo ad approfondirne due: recuperare le informazioni contenute dal Registro di sistema (Windows Registry) o utilizzare a tale scopo una lista statica di tipi MIME (MIME Type Map). Non prenderemo in considerazione tecniche che prevedono di effettuare delle interrogazioni a servizi esterni, in quanto riteniamo che un simile approccio sarebbe assolutamente inefficiente per questo tipo di necessità.

Recupero dal Registro di Sistema

Questa tecnica si basa sull’assunto, tanto ovvio quanto veritierio, che le informazioni relative ai tipi MIME più utilizzati siano già presenti in un archivio apposito nel nostro sistema operativo, per la precisione – nel caso dei sistemi Windows – in una apposita chiave di registro: tutto quello che dobbiamo fare è trovare il modo corretto per interrogarlo. Il vantaggio principale di questo approccio è dato dalla sua intrinseca semplicità: per effettuare questa interrogazione bastano poche linee di codice.

Il problema principale di questa tecnica è dato dalla necessità che i MIME-Type che ci interessa supportare siano effettivamente registrati nel Sistema Operativo dove l’applicazione è installata. Tutte le volte in cui questo assunto non è vero, la nostra interrogazione non restituirà alcun risultato e non saremo quindi in grado di recuperare il MIME Type corretto. Contrariamente a quello che si può pensare, non si tratta di un problema da poco: il sistema operativo possiede una collezione di MIME Type piuttosto minimale, quasi sempre limitata ai tipi di file che può aprire con una delle applicazioni installate. Il problema è particolarmente evidente se stiamo lavorando con una applicazione web, poiché i Server Web dispongono solitamente di un numero limitato di applicativi installati: lo stretto indispensabile per poter funzionare, così da tenere le risorse di sistema libere per IIS o altri servizi necessari.

Recupero da una MIME Type Map

Per risolvere le limitazioni del metodo precedente è possibile dotarsi (o realizzare manualmente) una classe apposita contenente un elenco dei tipi MIME corrispondenti a tutte le estensioni file più diffuse. Tra le molte disponibili in rete, la più completa – per C# – è senza dubbio quella fornita a corredo di questo progetto GitHub. Questa classe, oltre a contenere un numero enorme di MIME Type, prevede un mapping deterministico a due vie che consente anche di fare l’opposto, ovvero recuperare l’estensione corrispondente a un determinato tipo MIME.

Di seguito il codice completo della classe, aggiornato al 31 gennaio 2017:

Benché inevitabilmente prolisso, questo approccio risulta spesso molto più efficace e risolutivo del precedente. L’unico problema, ovviamente, è che trattandosi di una mappatura statica è necessario tenerla costantemente aggiornata man mano che nuovi MIME Type vengono definiti e/o rilasciati.

Fortunatamente l’autore del progetto ha pensato bene di creare un package NuGet costantemente aggiornato: è sufficiente aggiungerlo come dipendenza al nostro progetto ASP.NET per risolvere il problema una volta per tutte.

Un enorme ringraziamento a Samuel Neff per l’eccellente lavoro svolto!

UPDATE: il lettore Martino Bordin, che ringraziamo, ci avvisa che a partire dal framework 4.5 è finalmente stato aggiunto un metodo pubblico al namespace System.Web, denominato System.Web.GetMimeMapping, il quale consente di accedere al dictionary interno System.Web.MimeMapping – il quale contiene ben 342 MIME Type noti! Se utilizzate il framework 4.5 potete utilizzare questo metodo nativo e risparmiarvi ulteriori dipendenze o implementazioni ad-hoc, in caso contrario… Potete utilizzarlo lo stesso tramite le potenzialità del namespace System.Reflections come suggerito da questo eccellente post di David Haney, che – per chi non lo sapesse – è anche Engineering Manager di StackOverflow.

Ecco il codice della classe da lui pensata, denominata non a caso MimeMappingStealer, nella quale il dizionario viene esposto tramite Invoke all’interno di un metodo publlico:

Un grazie finale a Martino e a David: alla prossima!

RELATED POSTS

About Ryan

IT Project Manager, Web Interface Architect e Lead Developer di numerosi siti e servizi web ad alto traffico in Italia e in Europa. Dal 2010 si occupa anche della progettazione di App e giochi per dispositivi Android, iOS e Mobile Phone per conto di numerose società italiane.

View all posts by Ryan
  • Martino Bordin
    • Grazie mille, non ero al corrente che (finalmente) lo avessero reso pubblico! Ho aggiornato l’articolo menzionando il tuo suggerimento e (visto che c’ero) il contributo di David Haney per chi non avesse modo di aggiornare al framework 4.5: grazie ancora!

      • Martino Bordin

        Di niente..non so quale delle 2 sia più completa, dovrei aprire l’assembly del framework ..quasi sicuramente quella del package comunque credo 🙂