Загрузка файла на сервер исключает из памяти исключение
Я пытаюсь реализовать систему загрузки файлов с помощью asp.net web api, и у меня возникает проблема. Я пытаюсь получить данные многостраничной формы в поток памяти, чтобы он мог быть записан на диск или хранилище blob в зависимости от реализации уровня сервиса. Проблема в том, что он отлично работает для небольших файлов, но я пытаюсь загрузить файл размером 291 МБ и выкидывает исключение из памяти. Вот код:
if (!Request.Content.IsMimeMultipartContent())
{
Request.CreateErrorResponse(HttpStatusCode.UnsupportedMediaType, "Request must be multipart.");
}
var provider = new MultipartMemoryStreamProvider();
try
{
await Request.Content.ReadAsMultipartAsync(provider);
var infoPart = provider.Contents.Where(x => x.Headers.ContentDisposition.Name.Replace("\"", string.Empty) == "fileInfo").SingleOrDefault();
var filePart = provider.Contents.Where(x => x.Headers.ContentDisposition.Name.Replace("\"", string.Empty) == "filePart" && x.Headers.ContentDisposition.FileName != null).Single();
byte[] file = null;
using (Stream stream = filePart.ReadAsStreamAsync().Result)
{
using (MemoryStream memory = new MemoryStream())
{
stream.CopyTo(memory);
file = memory.ToArray();
}
}
string fileContentType = filePart.Headers.ContentType.MediaType;
FileDto result = _fileService.AddFileToResource(Variables);
string uri = Url.Link("DefaultGet", new { id = result.ID });
return Request.CreateResponse(HttpStatusCode.OK);
Часть, которая выдает ошибку, находится на
await Request.Content.ReadAsMultipartAsync(provider);
Точная ошибка
Ошибка записи MIME частичной части тела в выходной поток.
с внутренним исключением
Было исключено исключение типа 'System.OutOfMemoryException'.
Я попытался создать пользовательский BufferPolicySelector
, как показано во втором ответе этого сообщения и во многих других местах, но это, похоже, совсем не помогает.
Я также добавил в свой web.config:
<httpRuntime targetFramework="4.5" maxRequestLength="307200"/>
и
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="367001600"/>
</requestFiltering>
</security>
Ответы
Ответ 1
Одним из решений было бы использовать MultipartFormDataStreamProvider
вместо MultipartMemoryStreamProvider
, чтобы избежать исключения из памяти во время вызова
Request.Content.ReadAsMultipartAsync(..)
У меня возникла аналогичная проблема при попытке использовать MemoryStreamProvider при чтении содержимого файла MultiPart для большого файла ( > 100 МБ). Работа, которая работала для меня, заключалась в использовании MultipartFormDataStreamProvider
. Файл записывается на диск во время вызова ReadAsMultipartAsync и может быть позже загружен обратно, если вам это нужно в памяти.
Вот пример, взятый из:
Отправка данных формы HTML в веб-API: загрузка файлов и многостраничный MIME
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch(...)
Ответ 2
проверьте свой webconfig для ограничений на загрузку файлов
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="524288000"/>
</requestFiltering>
</security>
</system.webServer>
От OP Edit:
<httpRuntime targetFramework="4.5" maxRequestLength="307200"/>
maxRequestLength
находится в Кб - это порог буферизации, вы запрашиваете буфер 300 МБ - возможно, не очень хорошо. установите его ниже
Ответ 3
Проверьте права доступа к папке на сервере.
или
Поместите httpRuntime maxRequestLength в файл web.config, например:
<httpRuntime maxRequestLength="5242880" />