ASP.NET Web API supporta l'upload di file nell'ambito di una request Multipart tramite la classe MultipartFormDataStreamProvider. Si tratta di un oggetto che restituisce uno stream utilizzato poi dal framework per salvare il contenuto del body inviato dal browser.
L'utilizzo è piuttosto semplice. Immaginiamo di avere una form di questo tipo:
<form method="post" enctype="multipart/form-data" action="@Url.HttpRouteUrl("DefaultApi", new { controller = "upload" })"> <input type="file" id="upload" name="upload" multiple /> <br /> <input type="submit" /> </form>
Come possiamo notare, essa contiene al suo interno un Input di upload, con supporto anche a file multipli, e invia il contenuto in POST all'indirizzo del nostro UploadController. Il controller, a sua volta, contiene la logica per la ricezione dei file:
public class UploadController : ApiController { public async Task<HttpResponseMessage> PostFileAsync() { if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } var rootPath = HttpContext.Current.Server.MapPath("~/App_Data/"); var provider = new MultipartFormDataStreamProvider(rootPath); await this.Request.Content.ReadAsMultipartAsync(provider); return Request.CreateResponse(HttpStatusCode.OK, string.Join(";", provider.FileData.Select(x => Path.GetFileName(x.LocalFileName)))); } }
Questa action, che risponde alle richieste in POST, innanzi tutto effettua una verifica sulla tipologia di richiesta pervenuta. Nel caso in cui sia di tipo Multipart, crea un'istanza di MultipartFormDataStreamProvider passando il folder fisico in cui dovranno essere memorizzati i file. Successivamente il metodo ReadAsMultiPartAsync effettua il parsing della richiesta e sfrutta il provider per ottenere gli stream tramite cui memorizzare i file. L'ultima operazione consiste nel ritornare i LocalFileName in risposta al browser.
Come ultima nota, vale la pena sottolineare che il file viene salvato con un nome del tipo "BodyPart_{GUID}" autogenerato, invece di sfruttare il valore dell'header Content-Disposition. Si tratta di una best practice dal punto di vista della sicurezza, ma nulla ci vieta di memorizzare questa informazione separatamente in un database e associarla al nome del file generato, così che poi possiamo riproporre il nome originale come hint in caso di successivo download.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Documentare i servizi REST con Swagger e OpenAPI con .NET 9
Utilizzare una qualunque lista per i parametri di tipo params in C#
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Creare un webhook in Azure DevOps
Migliorare i tempi di risposta di GPT tramite lo streaming endpoint in ASP.NET Core
Disabilitare le run concorrenti di una pipeline di Azure DevOps
Testare l'invio dei messaggi con Event Hubs Data Explorer
Creare una libreria CSS universale: Cards
Creare una libreria CSS universale: Clip-path
Aprire una finestra di dialogo per selezionare una directory in WPF e .NET 8
Popolare una classe a partire dal testo, con Semantic Kernel e ASP.NET Core Web API
Utilizzare il metodo ExceptBy per eseguire operazione di sottrazione tra liste