c# - tutorial - asp.net core web api
Tratar con cargas de archivos grandes en ASP.NET Core 1.0 (2)
Cuando estoy subiendo archivos grandes a mi api web en ASP.NET Core, el tiempo de ejecución cargará el archivo en la memoria antes de que se active mi función para procesar y almacenar la carga. Con cargas grandes, esto se convierte en un problema ya que es lento y requiere más memoria. Para versiones anteriores de ASP.NET hay algunos artículos sobre cómo deshabilitar el almacenamiento en búfer de las solicitudes, pero no puedo encontrar información sobre cómo hacer esto con ASP.NET Core. ¿Es posible desactivar el almacenamiento en búfer de las solicitudes para que no me quede sin memoria en mi servidor todo el tiempo?
En su Controller
, simplemente puede usar los archivos de Request.Form.Files
para acceder a los archivos:
[HttpPost("upload")]
public async Task<IActionResult> UploadAsync(CancellationToken cancellationToken)
{
if (!Request.HasFormContentType)
return BadRequest();
var form = Request.Form;
foreach(var formFile in form.Files)
{
using(var readStream = formFile.OpenReadStream())
{
// Do something with the uploaded file
}
}
return Ok();
}
Use el Microsoft.AspNetCore.WebUtilities.MultipartReader
porque ...
puede analizar cualquier flujo [con] almacenamiento intermedio mínimo. Le da los encabezados y el cuerpo de cada sección, uno por uno, y luego hace lo que quiere con el cuerpo de esa sección (búfer, descarte, escritura en disco, etc.).
Aquí hay un ejemplo de middleware.
app.Use(async (context, next) =>
{
if (!IsMultipartContentType(context.Request.ContentType))
{
await next();
return;
}
var boundary = GetBoundary(context.Request.ContentType);
var reader = new MultipartReader(boundary, context.Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
// process each image
const int chunkSize = 1024;
var buffer = new byte[chunkSize];
var bytesRead = 0;
var fileName = GetFileName(section.ContentDisposition);
using (var stream = new FileStream(fileName, FileMode.Append))
{
do
{
bytesRead = await section.Body.ReadAsync(buffer, 0, buffer.Length);
stream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
section = await reader.ReadNextSectionAsync();
}
context.Response.WriteAsync("Done.");
});
Aquí están los ayudantes.
private static bool IsMultipartContentType(string contentType)
{
return
!string.IsNullOrEmpty(contentType) &&
contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}
private static string GetBoundary(string contentType)
{
var elements = contentType.Split('' '');
var element = elements.Where(entry => entry.StartsWith("boundary=")).First();
var boundary = element.Substring("boundary=".Length);
// Remove quotes
if (boundary.Length >= 2 && boundary[0] == ''"'' &&
boundary[boundary.Length - 1] == ''"'')
{
boundary = boundary.Substring(1, boundary.Length - 2);
}
return boundary;
}
private string GetFileName(string contentDisposition)
{
return contentDisposition
.Split('';'')
.SingleOrDefault(part => part.Contains("filename"))
.Split(''='')
.Last()
.Trim(''"'');
}
Referencias externas