Я работаю с веб-API ASP.NET Core 9, который принимает загрузку файла (потенциально большого размера) из одного из наших клиентских приложений и передает его во временный файл. на сервере, выполняет некоторую обработку, а затем загружает переупакованную версию файла в хранилище BLOB-объектов и отправляет некоторые метаданные о нем в базу данных. Все они находятся в Azure (приложения-контейнеры Azure, хранилище BLOB-объектов Azure, база данных SQL Azure). Запрос имеет тип Content-Type: multipart/form-data, с одним разделом для файла
Код: Выделить всё
Content-Disposition: form-data; name=""; filename=""
Проблема, которую я наблюдаю, заключается в том, что использование памяти контейнером примерно соответствует размеру загружаемого файла, что приводит к запуску контейнера. недостаточно памяти (см. скриншот). У меня сложилось впечатление, что потоковая передача загрузки непосредственно в хранилище файлов не должна использовать больше, чем необходимо для буферизации потока.
Попытки решения
Код в основном соответствует примеру из загрузки файлов. в ядре ASP.NET, за исключением того, что 1) здесь меньше проверки регистра, чтобы упростить тестирование, и 2) я вынужден иметь дело с потоком загрузки файла, поскольку реальный код будет передаваться по потоку в клиентскую библиотеку, которая будет наполнить его, обработать и т. д. Этот код вызывает наблюдаемую проблему с памятью.
Код: Выделить всё
///
/// Adds a new Document
///
[HttpPost("test", Name = nameof(AddDocumentAsync))]
[DisableFormValueModelBinding]
[DisableRequestSizeLimit]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task AddDocumentAsync()
{
if ( !HttpContext.Request.HasFormContentType )
return BadRequest("No file uploaded.");
string boundary = HttpContext.Request.GetMultipartBoundary();
if ( string.IsNullOrEmpty(boundary) )
return BadRequest("Invalid multipart form-data request.");
MultipartReader multipartReader = new MultipartReader(boundary, HttpContext.Request.Body);
MultipartSection? section = await multipartReader.ReadNextSectionAsync();
if ( section == null )
return BadRequest("No file found in request body.");
FileMultipartSection? fileSection = section.AsFileSection();
if ( fileSection?.FileStream == null )
return BadRequest("Invalid file.");
string tempDirectory = Path.GetTempPath();
string tmpPath = Path.Combine(tempDirectory, Path.GetRandomFileName());
using ( FileStream fs = new FileStream(tmpPath, FileMode.Create) )
await fileSection.FileStream.CopyToAsync(fs);
return Created();
}
Если Я меняю место назначения, чтобы файл передавался из fileSection.FileStream в хранилище BLOB-объектов, а не в локальный файл, проблем с памятью не наблюдаю.
Я тоже пробовал использование минимального API с привязкой модели для IFormFile. Отсюда я увидел, что по умолчанию, если размер файла превышает 64 КБ, он будет буферизован на диск, чего мне и хотелось. Я заметил, что файл растет в /tmp, но, к сожалению, использование памяти при этом решении росло с той же скоростью.
Я также попробовал смонтировать том хранилища для контейнера. , так как мне было интересно, использует ли контейнер память из-за отсутствия смонтированного тома хранилища. Я подключил экземпляр Azure Files в /blah и изменил место назначения для временного файла с /tmp на /blah. Я заметил, что файл правильно был передан в экземпляр хранилища файлов Azure, но проблема с памятью все равно наблюдалась и в этом случае, как и в других.
Наконец, я попробовал то же самое. код (фрагмент, опубликованный выше) в приложении веб-служб Azure и не заметил проблемы увеличения памяти. Аналогичным образом, я запустил приложение локально и не заметил увеличения памяти моей системы или процесса, как это было в приложении-контейнере Azure.
Вопрос
Я предполагаю, что я что-то неправильно понимаю или неправильно использую. Каков правильный способ потоковой передачи большого (от 1 ГБ до ? ГБ) файла multipart/form-data во временное хранилище для обработки и последующего удаления при работе с приложениями-контейнерами Azure и ASP.NET?
Подробнее здесь: https://stackoverflow.com/questions/792 ... ing-memory
Мобильная версия