Ограничения на загрузку файлов .Net 8. Попытка загрузить файл размером 89 МБ на мой контроллер API

С файлами меньшего размера (например, 30 МБ или около того) у меня нет проблем. Однако как только я пытаюсь загрузить файл размером 89 МБ в свой контроллер API, он выдает ошибки (Request Entity Too Large):

Из моего интерфейса:

POST http://localhost:21971/api/import/MediaUpload?sessionID=***&pid=*** net::ERR_FAILED 413 (Request Entity Too Large)

Мой серверный проект API .Net 8 содержит файл import.controller.cs:

[HttpPost]
 [Route("MediaUpload")]
 public async Task<IActionResult> MediaUpload([FromQuery] string sessionId, [FromQuery] string pid, [FromForm] ImportMediaUploadModel formData)
{
  IFormCollection form;

  try
  {
      form = await Request.ReadFormAsync();
      form.Keys.ToList().ForEach(key =>
      {
          if (key.Equals("MediaInfo", StringComparison.InvariantCultureIgnoreCase))
          {
              formData.MediaInfo = JsonConvert.DeserializeObject<List<MediaInfo>>(form[key]);
          }
      });
  }
  
     for (var i = 0; i < formData.Files?.Count; i++)
   {
       UploadFile(formData.Files[i]);
   }   
   // ...
   return Ok();
 } 
  
   private async void UploadFile(IFormFile file)
  {
      var thisFileName = file.FileName.Trim('\"');
      string? localPath = config[key: "ImportImageFolderPath"];
      string fullPath = Path.Combine(localPath, thisFileName);
      FileInfo fileInfo = new(fullPath);

      using var stream = System.IO.File.Create(fullPath);
      await file.CopyToAsync(stream);
  }

Я получаю ту же ошибку при загрузке в среду контроля качества (а не только на локальном хосте).

Я читаю некоторые документы, такие как эта, https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-8.0, но мне не хватает опыта -уровень знаний в последней версии .Net.

Заранее благодарим за любые советы о том, как справиться с ограничениями на загрузку файлов в .Net 8.

В нашем html-шаблоне две соответствующие части находятся здесь:

<input
    multiple
    #fileInputElement
    type = "file"
    style = "display:none;"
    (change) = "loadImagesFromInput($event)"
    accept = ".jpg, .tiff, .png, .gif, .bmp, .pdf, .avi, .wmv, .mp4, .mpg, .mpeg, .mov, .3gp, .3g2, .m4v, .fda"
  />

  <button mat-flat-button color = "primary" (click) = "openFileBrowser()" title = "Add Images" i18n-title = "@@addImages">
    <mat-icon svgIcon = "add"></mat-icon>
    <span i18n = "@@addImages">Add Images</span>
  </button>
  <span class = "spacer"></span>
  <button mat-flat-button color = "primary" [disabled] = "isSaveButtonDisabled()" (click) = "save()" title = "Save"
    i18n-title = "@@save">
    <mat-icon svgIcon = "save-to-disk"></mat-icon>
    <span i18n = "Button|Generic label for save option@@save">Save</span>
  </button>
  
  

и наша машинопись:

save(): void {
  this.isLoading = true;
  const sessId = this.appSession.session.SessionID;
  const params = { pID: this.selectedPat.PID };

  // Populate MediaInfo object (some conversions to match the server model)
  const mediaInfo: MediaInfo[] = this.importImages.map((image) => {
      return {
          PID: this.selectedPat.PID,
          /// add'l fields removed for brevity..
      };
  });

  const submitFormData = () => {
      const formData = new FormData();
      formData.append('MediaInfo', JSON.stringify(mediaInfo));
      formData.append('CsiXmlFolder', this.csiXmlFolder);
      for (let i = 0; i < this.importImages.length; i++) {
          if (this.importImages[i].image.date !== '' && this.importImages[i].image.date !== undefined) {
              this.importImages[i].image.date = formatDate(this.importImages[i].image.date, 'shortDate', 'en-US');
          }
      }

      for (const image of this.importImages) {
          formData.append('files', this.dataURItoBlob(image.image.TnUrl), image.image.name);
      }         

      const captureEndpoint = this.selectedDeviceObj.Url;            

      this.importService.saveImportObjects(formData, params, captureEndpoint).subscribe({
          next: (data) => {
    // toast msg, etc.
          },

      });
  };
  
  saveImportObjects(formData: FormData, params, endpointUri: string): Observable<HttpClient> {
    // NOTE: multipart and boundary header added by browser automatically.

    let url = '';
    let pid = '';       

    endpointUri = "http://localhost:21971/api/import/MediaUpload?"; // ** LOCAL DEV TESTING **
    
    if (endpointUri !== null) {
        url = `${endpointUri}sessID=${this.appSession.getSess()}&pId=${pid}`;
    }

    return this.http.post<any>(url, formData);
  }

просто примечание по безопасности: вам следует избегать этого: var thisFileName = file.FileName.Trim('\"'); а затем использовать это для создания файла. Никогда не доверяйте пользовательскому вводу. Вы должны полностью контролировать имя файла и расширение, используемое при сохранении файла на вашем сервере (расширение случаев/переключателя, если вам нужно... разрешить только определенные случаи.. используйте резервное расширение, если у вас нет для этого дела).

browsermator 09.08.2024 19:47

Также немного проще просто создать класс со всеми необходимыми полями... одно из них — IFormFile, а затем [привязать] его к POST. (вместо того, чтобы смешивать параметры запроса, подобные get, и POST, а затем получать необработанный запрос, повторять поля формы, десериализовать и т. д. Привязка .net выполнит всю работу за вас)

browsermator 09.08.2024 19:52

интерфейс немного слишком сложен. Вам нужно просто получить форму и создать из нее FormData... например: let form = document.getElementById('YourFormsID')! как HTMLFormElement; пусть formData = новый FormData (форма); Затем позвольте ASP.NET привязаться к форме. Прямо сейчас похоже, что вы создаете копию на стороне клиента, а затем отправляете ее... (дважды? как mediaInfo, а затем как файлы?) Все поля могут быть привязаны к их именам, файлы могут быть привязаны к List< IFormFile>ex: [BindProperty] public List<IFormFile> fileInputElement {get; набор; } (вы привяжете атрибут name)

browsermator 12.08.2024 19:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать атрибут [RequestSizeLimit(500*1024*1024)] для обработки запросов размером до 500 МБ.

[HttpPost]
[Route("MediaUpload")]
[RequestSizeLimit(500*1024*1024)]
public async Task<IActionResult> MediaUpload([FromQuery] string sessionId, [FromQuery] string pid, [FromForm] ImportMediaUploadModel formData)
{

Или вы можете настроить в Program.cs, как показано ниже:

builder.Services.Configure<FormOptions>(x => {
    //x.ValueCountLimit = int.MaxValue;
    x.MultipartBodyLengthLimit = long.MaxValue;
});

Третий способ — добавить файл web.config и использовать атрибут [DisableRequestSizeLimit], см. этот ответ.

RequestSizeLimit, похоже, не работает на уровне контроллера. Размер моего файла составляет 89 МБ, но он по-прежнему выдает ошибку «Слишком большой» во внешнем интерфейсе. Я даже ни разу не достиг точки останова на сервере (которая всегда работает для моих небольших загрузок файлов размером 30 МБ). Попробую идею с инъекцией строителя..

bob.mazzo 09.08.2024 20:09

не работает на уровне program.cs ни с конфигурацией builder.Services - FormOptions, ни с IISServerOptions. Для больших файлов он просто останавливается в браузере; никогда не попадает в мой серверный экземпляр vs2022, работающий на локальном хосте.

bob.mazzo 09.08.2024 22:33

вам, вероятно, следует включить свой внешний код в свой вопрос вместе с кодом для класса ImportMediaUploadModel.

browsermator 09.08.2024 23:16

Привет @bob.mazzo, как сказал браузер, пожалуйста, поделитесь своим кодом внешнего интерфейса.

Rena 12.08.2024 05:02

Привет @browsermator. Я опубликовал два соответствующих метода TS интерфейса, спасибо.

bob.mazzo 12.08.2024 16:23

на уровне IIS нам нужно было разобраться с опцией «Фильтр запросов» на веб-сайте. Я мог бы сделать это в web.config. Все это в этом посте inflectra.com/Support/KnowledgeBase/KB306.aspx .

bob.mazzo 14.08.2024 00:01

В качестве примечания: ничто из того, что я делал на уровне API C#, не пропускало бы объем, превышающий 30 МБ, на моем локальном компьютере.

bob.mazzo 14.08.2024 00:02

Конфигурация IIS, необходимая для увеличения максимального размера файла: https://www.inflectra.com/Support/KnowledgeBase/KB306.aspx.

В веб.конфигурации:

<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength = "2147483648" />
      </requestFiltering>
   </security>
 </system.webServer>

или

Прямо в настройках IIS - редактировать Фильтрация запросов.

Ответ @Rena выше также содержит следующую ссылку: web.config Как увеличить или установить неограниченный размер загружаемого медиафайла в проекте ASP.NET Core 2.2

Кажется, то же самое, что я поделился в ссылке третьего способа. Так это решение?

Rena 14.08.2024 03:40

@Rena - я был слишком сосредоточен на части C# API и, вероятно, пропустил часть web.config. Кроме того, я понял, что мы НЕ можем больше использовать web.config в нашем проекте .Net 8 (а скорее только appsettings.json); но я не осознавал, что когда мы публикуем/создаем проекты, действительно создается файл web.config.

bob.mazzo 14.08.2024 19:53

Другие вопросы по теме