A differenza di quanto accade in ASP.NET MVC, la classe ApiController di ASP.NET Web API non possiede un metodo diretto per restituire nella response lo stream di un file. Quando abbiamo questa necessità, tuttavia, possiamo creare una action che restituisca un HttpResponseMessage:
public HttpResponseMessage GetFile(string fileName) { var root = HttpContext.Current.Server.MapPath("~/App_Data"); var path = Path.Combine(root, fileName); var response = new HttpResponseMessage(HttpStatusCode.OK); // apro uno stream in lettura sul file var stream = new FileStream(path, FileMode.Open); response.Content = new StreamContent(stream); // imposto il mime type e le informazioni di download sull'header response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"); response.Content.Headers.ContentDisposition.FileName = fileName; return response; }
Come prima cosa calcoliamo il percorso assoluto del file; in questo esempio abbiamo supposto che si trovi all'interno della cartella App_Data. Il vantaggio di questa scelta è che tale cartella non è esposta da IIS e, quindi, l'accesso al file non potrà mai avvenire da direct link, ma sempre e solo in maniera controllata tramite la nostra action. Questo ci dà la possibilità, per esempio, di gestire policy di accesso, come il fatto che l'utente debba essere autenticato per effettuare il download.
Il passo successivo è quello di valorizzare come contenuto della response un oggetto di tipo StreamContent, popolato con uno stream sul file. Infine, per istruire il client sul modo corretto per gestire la response (nella fattispecie consigliandone il download), è buona norma impostare la content disposition come tipo attachment e suggerire il nome del file corretto.
Un'ultima nota riguarda il fatto che apriamo lo stream senza chiuderlo, cosa che potrebbe sollevare qualche dubbio: in realtà il disposing dell'oggetto FileStream è gestito internamente dall'oggetto StreamContent, quindi non dobbiamo preoccuparci di questo aspetto.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Evitare la command injection in un workflow di GitHub
Ottimizzazione dei block template in Angular 17
Utilizzare le Cache API di JavaScript per salvare elementi nella cache del browser
Usare le collection expression per inizializzare una lista di oggetti in C#
Utilizzare la session affinity con Azure Container Apps
Esportare ed analizzare le issue di GitHub con la CLI e GraphQL
Personalizzare l'errore del rate limiting middleware in ASP.NET Core
Inizializzare i container in Azure Container Apps
Sviluppare un'interfaccia utente in React con Tailwind CSS e Preline UI
Effettuare il deploy di immagini solo da container registry approvati in Kubernetes
Assegnare un valore di default a un parametro di una lambda in C#
Load test di ASP.NET Core con k6
I più letti di oggi
- Utilizzare WebAssembly con .NET, ovunque
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!
- Ottimizzare le performance delle collection con le classi FrozenSet e FrozenDictionary
- Utilizzare il trigger SQL con le Azure Function
- Disabilitare automaticamente un workflow di GitHub (parte 2)
- Ottimizzazione dei block template in Angular 17
- Paginare i risultati con QuickGrid in Blazor