Давайте представим, что я запускаю. NET Core API на устройстве с 1 ГБ памяти и 1 ГБ ОЗУ. Я хочу загрузить файл со своего веб-сайта прямо на FTP-сервер, без кеширования файла в памяти или на диске. У меня это работает для загрузки файлов, поскольку я в основном выступаю в качестве прокси, открывая файл FTP в потоке, а затем передавая его прямо на HttpContext.Request.Body
.
Для загрузки я хочу нажать на контроллер немедленно. Теперь я вижу, что он кешируется на диск, и это, вероятно, из-за моего атрибута EnableBuffering
. У меня есть обычный <form method="post" enctype="multipart/form-data">
, который отправляет POST на мой. NET Core backend. Контроллер выглядит так:
[EnableBuffering]
[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = long.MaxValue)]
[HttpPost("[action]")]
public async Task<IActionResult> Upload(string path)
{
if (!IsMultipartContentType(HttpContext.Request.ContentType))
return BadRequest("Not multipart request");
await _fileProvider.Upload(path);
return Ok();
}
EnableBuffering:
public class EnableBufferingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Request.EnableBuffering();
}
public void OnResourceExecuted(ResourceExecutedContext context) {}
}
Logi загрузки c:
public async Task Upload(string path)
{
const int buffer = 8 * 1024;
var request = _httpContextAccessor.HttpContext.Request;
var boundary = request.GetMultipartBoundary();
var reader = new MultipartReader(boundary, request.Body, buffer);
var section = await reader.ReadNextSectionAsync();
using (var client = await _ftpHelper.GetFtpClient())
{
while (section != null)
{
var fileSection = section.AsFileSection();
if (fileSection != null)
{
var fileName = fileSection.FileName;
var uploadPath = Path.Combine(path, fileName);
var stream = await client.OpenWriteAsync(uploadPath);
await section.Body.CopyToAsync(stream, buffer);
}
section = await reader.ReadNextSectionAsync();
}
}
}
Если я не включаю буферизацию, я get:
System.IO.IOException: неожиданный конец потока, контент, возможно, уже был прочитан другим компонентом.
Однако, включив буферизацию, я могу см. там написано:
Убедитесь, что requestBody можно читать несколько раз. Обычно тела запросов буферизируются в памяти; записывает запросы размером более 30 Кбайт на диск .
Так что эта часть имеет смысл. Однако как мне обойти эту проблему? Если я устанавливаю точку останова в первой строке метода Upload()
, а затем начинаю загрузку, он сначала загружает файл И ЗАТЕМ достигает точки останова.
Могу ли я обойти это чтобы он сразу попал в мой контроллер и начал загрузку на FTP-сервер, без предварительного сохранения на диск?