yotiky Tech Blog

とあるエンジニアの備忘録

ASP.NET Core と Azure App Service のアップロードのサイズ制限

目次

検証環境

  • APS.NET Core 5.0 Web アプリ(MVC
  • Azure App Service

ASP.NET Core

APS.NET Core では、.NET Core 2.0 以降、クロスプラットフォーム向け Web サーバーとして Kestrel が提供され、ASP.NET Core のプロジェクトテンプレートに既定で含まれ有効になっている。 .NET Framework の方は従来の IIS をベースにした動きとなる。

ASP.NET Core のテンプレートで生成される Program のうち ConfigureWebHostDefaults メソッドで UseKestrel が呼ばれる。

f:id:yotiky:20210325193650p:plain

ただし、ASP.NET Core であっても実行環境によって Kestrel、IIS のどちらかで動くことになる。

ローカルでデバッグ実行する時はどちらで動かすか選択できるようになっている。 IIS Express の場合はhttps://localhost:44393/、Kestrel の場合はhttps://localhost:5001/ とポートが異なる。

f:id:yotiky:20210325184052p:plain

App Service

ホスト

Visual Studio の 発行で 「Azure App Service(Windows)」を選択した場合や、ポータルで公開が「コード」の場合、ASP.NET Core のプロジェクトは IIS でホストされる。

f:id:yotiky:20210325194223p:plain

f:id:yotiky:20210325194159p:plain

Visual Studio の 発行で 「Azure App Service(Linux)」または「Azure App Service コンテナー」を選択した場合や、ポータルで公開が「Docker」でOSが「Linux」の場合、ASP.NET Core のプロジェクトは Kestrelでホストされる。

f:id:yotiky:20210325194223p:plain

f:id:yotiky:20210325194517p:plain

※Web App for Containers の Windows コンテナは2020年9月に一般提供され、料金プランは「Premium V3」から選択できる。お高いのでスキップ。*1

リクエスト本文のサイズ制限

IIS

IIS でホストされる場合、リクエスト本文のデフォルトの制限は3000万バイト(約28.6MB)となる。 制限を変更するには、web.config を追加して maxAllowedContentLength を設定する。 以下は1億バイト(約95.4MB)になる。

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

9500万バイトのファイルをアップロードすると成功してファイルサイズが返ってくる。

f:id:yotiky:20210325195002p:plain
結果
f:id:yotiky:20210325195014p:plain

1億バイトのファイルをアップロードするとエラーメッセージが表示される。

f:id:yotiky:20210325194908p:plain

f:id:yotiky:20210325195707p:plain
The page was not displayed because the request entity is too large.

Kestrel

Kestrel のリクエスト本文も最大サイズは3000万バイト(約28.6MB)がデフォルトである。 Bodyなので添付ファイルのみではなく送信するリクエスト全文のサイズになる。

アプリ全体でグローバルに制限を変更するには、Program 内で MaxRequestBodySize を設定する。 以下は1億バイト(約95.4MB)になる。

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel((context, options) =>
            {
                options.Limits.MaxRequestBodySize = 100000000;
            })
            .UseStartup<Startup>();
        });

9500万バイトのファイルをアップロードすると成功してファイルサイズが返ってくる。

f:id:yotiky:20210325195002p:plain
結果
f:id:yotiky:20210325195014p:plain

1億バイトのファイルをアップロードすると 400 が返ってくる。

f:id:yotiky:20210325194908p:plain
f:id:yotiky:20210325194858p:plain

グローバル設定の他に、コントローラーやアクション単位でも制限を設定できる。どちらも RequestSizeLimitAttribute を付与して設定する。無制限にする場合は DisableRequestSizeLimitAttribute も用意されている。

[AutoValidateAntiforgeryToken]
[RequestSizeLimit(100000000)]
public class FileController : Controller
{
    [HttpPost]
    [RequestSizeLimit(100000000)]
    public IActionResult Upload(IFormFile file)
    {
        return Ok(new { file.Length });
    }
    [HttpPost]
    [DisableRequestSizeLimit]
    public IActionResult UploadUnlimited(IFormFile file)
    {
        return Ok(new { file.Length });
    }
}

マルチパート本文のサイズ制限

リクエスト本文のサイズ制限の他に Form セクションのマルチパート本文にもサイズ制限がある。 こちらは IIS と Kestrel で動作も設定も同じである。 デフォルトの上限は 128MB(134,217,728バイト)となる。

ファイルをアップロードするだけの Form の場合128MBのファイルであれば成功する。

f:id:yotiky:20210325202024p:plain
結果
f:id:yotiky:20210325202032p:plain

1バイト足したファイルだと 400 が返ってくる。 f:id:yotiky:20210325202056p:plain
f:id:yotiky:20210325194858p:plain

アプリ全体でグローバルに制限を変更するには、Startup 内で MultipartBodyLengthLimit を設定する。 以下の例は 256 MB が上限になる。

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.Configure<FormOptions>(options =>
    {
        options.MultipartBodyLengthLimit = 268435456; // 256 MB
    });
}

先程失敗した「128MB1byte.zip」のアップロードが成功するようになる。

結果
f:id:yotiky:20210325203256p:plain

グローバル設定の他に、コントローラーやアクション単位でも制限を設定できる。どちらも RequestFormLimitsAttributeMultipartBodyLengthLimit を設定して付与する。 以下の例は 256 MB が上限になる。

[AutoValidateAntiforgeryToken]
[RequestFormLimits(MultipartBodyLengthLimit = 268435456)]
public class FileController : Controller
{
    [HttpPost]
    [RequestFormLimits(MultipartBodyLengthLimit = 268435456)]
    public IActionResult Upload(IFormFile file)
    {
        return Ok(new { file.Length });
    }
}

おまけ (Azure Functions)

Azure Functions は リクエスト本文の上限が 100 MB になっている。これは変更できない。 あと httpRuntime 要素じゃなく requestLimits 要素で指定されてる。

HTTP 要求の長さは 100 MB (104,857,600 バイト) に、URL の長さは 4 KB (4,096 バイト) バイトに制限されています。 これらの制限は、ランタイムの Web.config ファイルの httpRuntime 要素で指定されています。

参考