Kiedy przesyłam duże pliki do mojego interfejsu API w ASP.NET Core, środowisko wykonawcze załaduje plik do pamięci, zanim moja funkcja do przetwarzania i przechowywania wysyłania zostanie zwolniona . W przypadku dużych przesyłek staje się to problemem, ponieważ jest powolny i wymaga więcej pamięci. Wcześniejszych wersjach ASP.NET there are some articles, jak wyłączyć buforowanie żądań, ale nie jestem w stanie znaleźć żadnych informacji, jak to zrobić z ASP.NET Core. Czy można wyłączyć buforowanie żądań, aby nie zabrakło pamięci na moim serwerze przez cały czas?Radzenie sobie z przesyłaniem dużych plików na ASP.NET Core 1.0
Odpowiedz
pomocą Microsoft.AspNetCore.WebUtilities.MultipartReader
ponieważ ...
można analizować każdą strumień [z] minimalnym buforowania. Daje ci nagłówki i treść każdej sekcji po jednej na raz, a następnie robisz, co chcesz, z treścią tej sekcji (bufor, odrzuć, napisz na dysk itp.).
Oto przykład oprogramowania pośredniego.
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.");
});
Oto pomocnicy.
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('"');
}
Odniesienia zewnętrzne
Wygląda na to, że ten kod działa idealnie na dnx451, ale ma wyciek pamięci na dnxcore50. Może to być coś, co jest naprawiane dla RC2. – Martin
Funkcja GetFileName() z powyższego fragmentu powoduje, że serwer buforuje cały plik. Zastąpiłem go losową nazwą pliku, ale po zapisaniu wszystkich porcji do pliku widzę, że użycie pamięci zwiększyło się o amefount równą rozmiarowi pliku. Może być w porządku, jeśli dalsze GC się go pozbędzie. Ale wydaje się, że nie jest dobrze – EvAlex
@EvAlex 'GetFileName' po prostu analizuje ciąg znaków. Czy istnieje coś innego, co dzieje się przed lub po tym, może spowodować, że serwer buforuje cały plik? –
w twojej Controller
można po prostu użyć Request.Form.Files
aby uzyskać dostęp do plików:
[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. Ładowanie dużych plików XML i radzenie sobie z MemoryError
- 2. Wykrywanie programu ASP.NET Core 1.0
- 3. Projekt ASP.NET Core 1.0 F #
- 4. Problem z przesyłaniem pliku
- 5. Radzenie sobie z ograniczeniami EWS
- 6. Radzenie sobie z przestarzałym android.text.ClipboardManager
- 7. Radzenie sobie z plikami nagłówkowymi doładowania
- 8. Radzenie sobie z n ASP.NET Trasy ukośników przy użyciu regex
- 9. Problemy z przesyłaniem plików Grailsa
- 10. Radzenie sobie z błędami podczas kopiowania z
- 11. Uwierzytelnianie plików cookie Asp.Net Core
- 12. Event-sourcing: Radzenie sobie z danymi pochodnymi
- 13. Rodzaje Typescript Union: Radzenie sobie z interfejsami
- 14. Radzenie sobie z niedokładnym zegarem systemowym
- 15. Radzenie sobie ze znakami mowy z String.match
- 16. Radzenie sobie z kolizją nazw modułów
- 17. Radzenie sobie z Azure inscenizacją crazy URL
- 18. Radzenie sobie z ogromnymi wykresami - podróżujący sprzedawca
- 19. Radzenie sobie z czasami i po północy
- 20. Czyste radzenie sobie z błędami zaokrąglania/akumulacji
- 21. Jak dodać referencję projektu do projektu ASP.NET Core 1.0 MVC
- 22. Radzenie sobie z przecinkami w CSV
- 23. Radzenie sobie z bardzo długim zadaniem prowizji
- 24. Android - radzenie sobie z dialogiem na ekranie Zmiana orientacji ekranu
- 25. R: Radzenie sobie z true, false, Na i NaN
- 26. Jednostka Entity Framework Core 1.0 z oprogramowaniem warstwy pośredniej Asp.Net Core lub filtrem Mvc
- 27. Problem kompilacji Resharpera z rdzeniem ASP.NET 1.0
- 28. Jak skonfigurować uwierzytelnianie w programie ASP.NET Core 1.0
- 29. Bibliotekę .NET Core 1.0 z pakietu WPF
- 30. Szyny 3 wieloetapowy formularz z przesyłaniem plików
Piszę swój backend do przesyłania plików, aby obsługiwał przesyłanie plików w małych porcjach zgodnie z api dla [flowjs] (https://github.com/flowjs/flow.js) – jltrem
Witaj @jltrem, czy mógłbyś podzielić się rdzeniem asp.net? kontroler i kod kątowy, który obsługuje pliki przesłane za pomocą flowjs? –