Wenn ich große Dateien auf meine Web-API in ASP.NET Core hochlade, lädt die Runtime die Datei in den Speicher, bevor meine Funktion zum Verarbeiten und Speichern des Uploads ausgelöst wird . Bei großen Uploads wird dies zu einem Problem, da es langsam ist und mehr Speicher benötigt. Für frühere Versionen von ASP.NET there are some articles zum Deaktivieren der Pufferung von Anforderungen, aber ich bin nicht in der Lage, Informationen zu finden, wie dies mit ASP.NET Core zu tun. Ist es möglich, die Pufferung von Anfragen zu deaktivieren, damit auf meinem Server nicht ständig der Speicher ausgeht?Umgang mit großen Dateiuploads auf ASP.NET Core 1.0
Antwort
Verwenden Sie die Microsoft.AspNetCore.WebUtilities.MultipartReader
, weil es ...
jeden Stream analysieren kann [mit] minimal Pufferung. Es gibt Ihnen die Header und den Body jedes Abschnitts nacheinander und dann machen Sie, was Sie wollen mit dem Körper dieses Abschnitts (Puffer, verwerfen, auf die Festplatte schreiben, etc.).
Hier ist ein Middleware-Beispiel.
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.");
});
Hier sind die Helfer.
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('"');
}
Externe Referenzen
Es scheint, dass dieser Code perfekt auf dnx451 funktioniert, aber es hat einen Speicherverlust auf dnxcore50. Könnte etwas sein, das für RC2 behoben wird. – Martin
GetFileName() aus dem obigen Snippet bewirkt, dass der Server die gesamte Datei puffert. Ich ersetzte es durch den Namen der randomisierten Datei, aber nachdem ich alle Blöcke in die Datei geschrieben habe, sehe ich, dass die Speichernutzung um den Betrag der Dateigröße erhöht wird. Es kann tatsächlich in Ordnung sein, wenn weitere GC es loswerden werden. Aber scheint nicht ok – EvAlex
@EvAlex 'GetFileName' analysiert nur eine Zeichenfolge. Gibt es noch etwas, das vor oder nach dem passiert, was dazu führen könnte, dass der Server die gesamte Datei puffert? –
In Ihrem Controller
Sie können einfach Request.Form.Files
verwenden, um die Dateien zuzugreifen:
[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();
}
- 1. ASP.NET Core 1.0 Protokollierung
- 2. ASP.NET Core 1.0 SynchronizationContext
- 3. ASP.NET CORE 1.0, Imitation
- 4. ASP.NET Core 1.0 Mocking
- 5. Aspnet.Security.OpenIdConnect.Server Fehler auf ASP.net Core 1.0 RTM
- 6. ASP.NET Core 1.0 RC2 auf ARM
- 7. Dropdownmenü in ASP.NET Core 1.0
- 8. Transaktionen mit ASP.NET Core 1.0 Identity UserManager
- 9. package.json in ASP.NET Core 1.0
- 10. ASP.NET Core 1.0 OAuth Server mit Openiddict
- 11. Verhindern Browser-Timeout bei großen Dateiuploads
- 12. Umgang mit großen Bildern
- 13. ASP.NET Core 1.0 RTM-Lokalisierung funktioniert nicht
- 14. ASP.NET Core 1.0 Identity 3 & BaseEntity
- 15. Erstellen RSS-Feed in asp.net Core 1.0
- 16. ASP.NET Core 1.0 Benennung von Anwendungsressourcen
- 17. Wo ist "system.web.mvc.ajaxhelper" in asp.net core 1.0
- 18. Erfordern Autorisierung in ASP.NET Core 1.0
- 19. ASP.NET Core 1.0 für Enterprise-Anwendungen
- 20. Konfigurieren der Authentifizierung in ASP.NET Core 1.0
- 21. Verwendung von SignalR in ASP.NET Core 1.0
- 22. ASP.NET-Core 1.0 Dynamische Anzeige Modellfelder
- 23. Unterstützt ASP.net core 1.0 RC2 Kompilierungsvorverarbeitung?
- 24. Erste Fehler in Asp.Net Core-1.0
- 25. Lokalisierung von IdentityErrorDescriber in ASP.Net Core 1.0
- 26. SigningCredentials auf .NET-Core 1.0
- 27. ASP.NET Core 1.0 - API-Referenz auf ein .NET 4.5-Projekt
- 28. Remotedebugging einer ASP.NET Core 1.0-Anwendung auf Azure App Service
- 29. ASP.NET 4.6 und ASP.NET Core 1.0 Freigabe Authentifizierung
- 30. Bereitstellen von asp.net Core 1.0 Website auf AWS
Ich schreibe mein Datei-Upload-Backend, um das Hochladen von Dateien in kleinen Blöcken gemäß der API für [flowjs] (https://github.com/flowjs/flow.js) zu unterstützen. – jltrem
Hallo @jltrem, kannst du bitte den asp.net-Core teilen Controller und Winkelcode, der mit flowjs hochgeladene Dateien behandelt? –