Итак, ваша проблема вполне очевидна. Вы пытаетесь загрузить файл размером 500+ МБ. В вашем контроллере вы получаете размер файлов, а затем делаете это:
byte[] data = new byte[fileSize];
Вы не хотите этого делать ... IFormFile
уже дает вам Stream
, который вы можете прочитать из. В частности, все, что реализуется из IFormFile
, должно реализовывать следующие методы:
void CopyTo(Stream target);
Task CopyToAsync(Stream target, CancellationToken cancellationToken = default(CancellationToken));
Stream OpenReadStream();
Итак, если у вас есть поток, готовый к go, зачем вы копируете этот поток в память?
Быстрый и грязный способ обойти это - сбросить IFormFile
на диск. Затем откройте файл на диске и переместите / выполните потоковую передачу туда, где это необходимо. go:
[HttpPost("{id}")]
[DisableRequestSizeLimit]
public async Task<IActionResult> UploadLargeFiles(string id, [FromForm]IFormFile file)
{
FileInfo fi = null;
try
{
// this is from my code, but you want to store this
// somewhere on disk that works with your hosting setup.
fi = _fileStorageService.GetTempFile();
// open a stream for writing and copy it over
using (var s = fi.OpenWrite())
{
await file.CopyToAsync(s).ConfigureAwait(false);
}
}
catch { fi?.Delete(); fi = null; }
if(fi == null) { /* return a 500 error */ }
// TODO: At this point, you have a file that you can open and
// stream or move to where ever you want
// Make sure that when you are done with the file, that you
// delete it if you no longer need it.
}
Итак, теперь вы являетесь владельцем файла, он в вашем распоряжении. Теперь вы можете отправить его в BackgoundService
или другой HostedService
- или даже в другую временную, ограниченную или одноэлементную службу для обработки. Небо - предел.
Этот метод может быть не самым эффективным, потому что вы, по сути, копируете файл с одной части диска на другую.
Вы можете срезать этот угол и взять поток, возвращенный OpenReadStream
из IFormFile
, и передать его процессу, который отправит этот поток в другую службу, вроде того, как мы использовали CopyToAsync()
для отправки его в файл на диске.
Просто имейте в виду, что после завершения работы этой конечной точки IFormFile
будет удален. Так что вам придется sh завершить обработку в контексте этого выполнения.
В конце дня, что бы вы ни делали, не считывайте файл в память. Он уже проживает в IFormFile
. Нет причин повторять его дублирование в памяти.