ASP.NET Core:come ricevere un file in una richiesta API Web

 C Programming >> Programmazione C >  >> Tags >> API
ASP.NET Core:come ricevere un file in una richiesta API Web

Quando il client pubblica un file in una richiesta multipart/form-data, viene caricato in un oggetto IFormFile. Contiene informazioni sul file (come il nome del file) ed espone il contenuto del file come flusso. Ciò ti consente di salvare il file o elaborarlo come preferisci.

È possibile accedere all'oggetto IFormFile tramite Request.Form.Files:

[Route("[controller]")]
[ApiController]
public class FilesController : ControllerBase
{
	[HttpPost]
	public async Task<IActionResult> Post()
	{
		IFormFile file = Request.Form.Files.FirstOrDefault();

		//process file content

		return Ok($"Received file {file.FileName} with size in bytes {file.Length}");
	}
}
Code language: C# (cs)

Oppure puoi aggiungere un parametro IFormFile (o aggiungerlo come proprietà del modello) e mapperà i dati del modulo del file al parametro per nome:

[Route("[controller]")]
[ApiController]
public class FilesController : ControllerBase
{
	[HttpPost]
	public async Task<IActionResult> Post(IFormFile file)
	{
		//process file content

		return Ok($"Received file {file.FileName} with size in bytes {file.Length}");
	}
}
Code language: C# (cs)

Nota:assicurati che il nome del parametro IFormFile corrisponda all'attributo del nome del file nei dati del modulo, altrimenti non verrà mappato e sarà nullo.

Salvataggio su disco

IFormFile espone il contenuto del file come flusso. Puoi salvarlo su disco creando un FileStream e copiando il flusso di file su di esso.

Ecco un esempio di salvataggio del file su disco:

using System.IO;

[HttpPost]
public async Task<IActionResult> Post(IFormFile file)
{
	if (file.Length <= 0)
		return BadRequest("Empty file");

	//Strip out any path specifiers (ex: /../)
	var originalFileName = Path.GetFileName(file.FileName);

	//Create a unique file path
	var uniqueFileName = Path.GetRandomFileName();
	var uniqueFilePath = Path.Combine(@"C:\temp\", uniqueFileName);

	//Save the file to disk
	using (var stream = System.IO.File.Create(uniqueFilePath))
	{
		await file.CopyToAsync(stream);
	}

	return Ok($"Saved file {originalFileName} with size {file.Length / 1024m:#.00} KB using unique name {uniqueFileName}");
}
Code language: C# (cs)

Nota:per semplicità, codifica la directory di caricamento del file (C:\temp\). Realisticamente, vorresti inserire questa impostazione con il resto dei tuoi dati di configurazione.

Quando invio una richiesta a questo, salva il file in una directory di caricamento file dedicata e utilizza un nome file univoco. Restituisce la risposta:

Saved file class-hierarchy-diagram.png with size 6.88 KB using unique name hseadpgk.xgfCode language: plaintext (plaintext)

IFormFile come proprietà del modello

In molti casi, ti consigliamo di pubblicare il file con i dati associati come parte di un modello. Puoi aggiungere IFormFile come proprietà del modello.

public class Document
{
	public string Title { get; set; }
	public string Version { get; set; }
	public IFormFile File { get; set; }
}
Code language: C# (cs)

Quindi includi il modello come parametro e applica l'attributo [FromForm]:

[HttpPost]
public async Task<IActionResult> Post([FromForm]Document document)
{
	//process file 

	return Ok($"Processed document {document.Title} v{document.Version} - {document.File.FileName}");
}
Code language: C# (cs)

Caricherà i dati del file nella proprietà IFormFile e potrai elaborarli/salvarli come preferisci.

Nota:includi l'attributo [FromForm] durante la mappatura dei dati del modulo su un modello, altrimenti riceverai una risposta 415-Media non supportato.

Limiti delle dimensioni dei file

I limiti di dimensione del file/richiesta sono diversi in base al server web. Nelle app Web ospitate da Kestrel, i principali limiti predefiniti sono:

  • Richiedi limite di dimensione di 30 MB.
  • Limite di dimensioni della sezione del modulo in più parti di 128 MB.

Puoi modificare i limiti per tutte le richieste o per azione. Ti consiglio di modificare i limiti per azione, perché probabilmente vorrai limiti drasticamente diversi per le azioni che riguardano il caricamento di file rispetto ad altre azioni.

Ecco un esempio di aumento del limite delle dimensioni della richiesta a 60 MB:

[HttpPost]
[RequestSizeLimit(bytes: 60_000_000)]
public async Task<IActionResult> Post(IFormFile file)
{
	//process file 

	return Ok();
}
Code language: C# (cs)

I file vengono inviati come dati del modulo, quindi devi anche tenere conto dei limiti delle dimensioni del modulo. Utilizzerà il limite minimo applicabile per determinare se la richiesta ha superato i limiti. Puoi modificare i limiti delle dimensioni del modulo con l'attributo [RequestFormLimits].

Ricezione di più file

Esistono due modi per ricevere più file:

  • Aggiungi un parametro IFormFile per ogni file.
  • Utilizza IEnumerable per ricevere più file in un unico parametro.

La prima opzione è migliore quando sai esattamente quanti file devi trasferire al client. La seconda opzione è migliore quando il client può inviare un numero qualsiasi di file.

Ecco un esempio di ricezione di più file:

[HttpPost]
public async Task<IActionResult> Post(IEnumerable<IFormFile> files)
{
	foreach(var file in files)
	{
		//process each file
	}

	return Ok();
}
Code language: C# (cs)

Quando si utilizza questo approccio, il client dovrà utilizzare lo stesso nome per ogni file aggiungono ai dati del modulo.