ASP.NET Core:cómo recibir un archivo en una solicitud de API web

 C Programming >> Programación C >  >> Tags >> API
ASP.NET Core:cómo recibir un archivo en una solicitud de API web

Cuando el cliente publica un archivo en una solicitud de datos de formulario/varias partes, se carga en un objeto IFormFile. Contiene información del archivo (como el nombre del archivo) y expone el contenido del archivo como una secuencia. Esto le permite guardar el archivo o procesarlo como desee.

Puede acceder al objeto IFormFile a través de 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)

O puede agregar un parámetro IFormFile (o agregarlo como una propiedad del modelo), y asignará los datos del formulario de archivo al parámetro por nombre:

[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:asegúrese de que el nombre del parámetro IFormFile coincida con el atributo de nombre del archivo en los datos del formulario; de lo contrario, no se asignará y será nulo.

Guardar en disco

IFormFile expone el contenido del archivo como una secuencia. Puede guardar esto en el disco creando un FileStream y copiando el flujo de archivos en él.

Este es un ejemplo de cómo guardar el archivo en el 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:para simplificar, esto codifica el directorio de carga de archivos (C:\temp\). Siendo realistas, le gustaría poner esta configuración con el resto de sus datos de configuración.

Cuando envío una solicitud a esto, guarda el archivo en un directorio de carga de archivos dedicado y usa un nombre de archivo único. Devuelve la respuesta:

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

IFormFile como propiedad del modelo

En muchos casos, querrá publicar el archivo con los datos asociados como parte de un modelo. Puede agregar IFormFile como una propiedad del modelo.

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

Luego incluya el modelo como parámetro y aplique el atributo [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)

Cargará los datos del archivo en la propiedad IFormFile y podrá procesarlos/guardarlos como desee.

Nota:Incluya el atributo [FromForm] al asignar datos de formulario a un modelo; de lo contrario, obtendrá una respuesta 415- Medios no admitidos.

Límites de tamaño de archivo

Los límites de tamaño de archivo/solicitud son diferentes según el servidor web. En las aplicaciones web alojadas en Kestrel, los principales límites predeterminados son:

  • Límite de tamaño de solicitud de 30 MB.
  • Límite de tamaño de sección de formulario de varias partes de 128 MB.

Puede cambiar los límites para todas las solicitudes o por acción. Recomiendo cambiar los límites por acción, porque probablemente querrá límites drásticamente diferentes para las acciones relacionadas con la carga de archivos en comparación con otras acciones.

Este es un ejemplo de cómo aumentar el límite de tamaño de la solicitud a 60 MB:

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

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

Los archivos se envían como datos de formulario, por lo que también debe tener en cuenta los límites de tamaño del formulario. Utilizará el límite aplicable más pequeño para determinar si la solicitud ha excedido los límites. Puede cambiar los límites de tamaño del formulario con el atributo [RequestFormLimits].

Recibir varios archivos

Hay dos formas de recibir varios archivos:

  • Agregue un parámetro IFormFile para cada archivo.
  • Utilice IEnumerable para recibir varios archivos en un único parámetro.

La primera opción es mejor cuando sabe exactamente cuántos archivos necesita que el cliente pase. La segunda opción es mejor cuando el cliente puede enviar cualquier cantidad de archivos.

Este es un ejemplo de cómo recibir varios archivos:

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

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

Al usar este enfoque, el cliente deberá usar el mismo nombre por cada archivo que agregan a los datos del formulario.