WebSurfer's Home

Filter by APML

ASP.NET Core で 64KB 以上のファイルアップロード失敗

by WebSurfer 7. November 2025 13:44

元の話は Microsoft Q&A のスレッド ASP .Net Core 6 / IIS Server File Upload Restriction ? のものです。Windows Server の IIS 10 でホストされる ASP.NET Core Web アプリのファイルアップロードで、ファイルサイズが 64KB より小さい場合は問題ないが、それを超えるとアップロードに失敗するという話です。

ファイルアップロード

なお、Microsoft Q&A の質問者さんのコードは、サイズが 64KB より大きいファイルのアップロードを含め、期待通り動くことは自分の環境でですが確認しました。multipart/form-data 形式で CSRF トークンと input type="file" で選んだファイルが送信され、サーバー側で OnPost メソッドの引数 IList<IFormFile> files にバインドされます。

たった 64KB 超でアップロードに失敗するということが一般的に起きているとすると FAQ 的な話になるはずですが、過去にそのような話は聞いたことがないので、多分 Microsoft Q&A の質問者さんの環境独自の問題だと思われます。なので、一般的には参考にならない話かもしれませんが、調べたことを備忘録として書いておきます。

Microsoft のドキュメント「ASP.NET Core でファイルをアップロードする」の「ファイル アップロードのシナリオ」のセクションに、

"1 つで 64 KB を超えるバッファーファイルは、メモリからディスク上の一時ファイルに移動されます。より大きな要求の一時ファイルは、ASPNETCORE_TEMP 環境変数で指定された場所に書き込まれます。 ASPNETCORE_TEMP が定義されていない場合、ファイルは現在のユーザーの一時フォルダーに書き込まれます。"

・・・と書いてあります。

「メモリからディスク上の一時ファイルに移動」するということは、メモリのデータをファイルとして特定のフォルダーに書き込むということになります。書き込むには、それを行うプロセスのアカウントが書き込み先のフォルダーに対して書き込み権限を持っていなければなりません。

Microsoft Q&A のスレッドの質問者さんのケースでは、しきい値 64KB を超えるファイルがアップロードされた際、ASP.NET がそれをメモリからディスク上に一時ファイルとして移動しようとしたが、移動み先のフォルダーに書き込み権限が無くて失敗したということだと思われます。

しきい値を超えなければメモリにバッファされたままになりますので、ファイルサイズが 64KB より小さい場合は問題なかったということのようです。

しきい値 64KB は FormOptions.MemoryBufferThreshold プロパティで設定されています。デフォルトは 64KB ですが変更は可能です。

質問者さんの環境で、Program.cs に以下の設定を追加して、しきい値を 128KB に変更したらアップロードに成功したということですので、やはり原因は移動先のフォルダーに書き込み権限が無かったということだったと思われます。

services.Configure<FormOptions>(options =>
{
    options.MemoryBufferThreshold = 131072; // 128 KB
});

上の方法でしきい値を増やすのは、応急処置であればともかく、恒久処置として適切かはよく検討した方が良さそうです。

なぜなら、同時に多数のユーザーがファイルをアップロードするようなサイトでは、MemoryBufferThreshold を増やすとメモリが分断されてすぐにメモリ不足になってしまう恐れがあるからです。恒久処置としてはアクセス権の問題を解決してディスク上に一時ファイルとして移動できるようにするのが良さそうです。

逆に、めったに大きなファイルのアップロードはしないサイトなら (例えば、個人のブログのようなサイト)、ディスクにバッファリングされないように MemoryBufferThreshold の設定値を大きくしておく方が良いかもしれません。

では、アクセス権の問題を解決してディスク上に一時ファイルとして移動できるようにするにはどうするかですが、基本的には IIS のワーカープロセスのアカウントに移動先のフォルダーに対する書き込み・読み出し権限を与えるということになります。

移動先のフォルダーがどこにあるかですが、ASPNETCORE_TEMP 環境変数で指定されている場合はそこになります。ASPNETCORE_TEMP 環境変数の設定がない場合は (Windows Server ではデフォルトではその設定はないそうです)、現在のユーザーの一時フォルダーになります。

現在のユーザーの一時フォルダーはどこにあるかと言うと、Windows OS では %temp% で示されるフォルダーです。具体的には、IIS のワーカープロセスのアカウント(アプリケーションプールの Identity)がユーザープロファイルを持っている場合は以下のフォルダーとなります。

C:\Users\<ユーザー名>\AppData\Local\Temp

例えば、IIS Manager を使って AspNetCoreCookieAuth と言う名前のアプリケーションプールを作成したとします。その詳細設定は以下のようになります。

アプリケーションプールの詳細設定

名前が AspNetCoreCookieAuth、プロセスモデルの ID が ApplicationPoolIdentity、ユーザープロファイルの読み込みが True になっているとことに注目してください。デフォルトでそのようになるはずです。

このアプリケーションプールで ASP.NET Core アプリを動かすとアプリケーションプール名で C:\Users フォルダ下に以下の画像の通り AspNetCoreCookieAuth と言う名前のフォルダが生成されます。

Temp

%temp% は C:\Users\AspNetCoreCookieAuth\AppData\Local\Temp になりますが、そのフォルダも生成されています。

フォルダ AspNetCoreCookieAuth のプロパティを開いてセキュリティタブを見ると、ユーザー AspNetCoreCookieAuth(アプリケーションプールの Identity)にフルコントロール権限が与えられているところに注目してください。

なので、この状態(デフォルト)であれば、移動先のフォルダーに対する書き込み・読み出し権限は既に与えられているので、何もする必要はありません。それゆえ、たった 64KB 超でアップロードに失敗するということは自分は初耳だったのだと思います。

アプリケーションプールの Identity がユーザープロファイルを持たないケースもあるそうです。それはアプリケーションプールを作成する際プロセスモデルの ID に (1) ユーザープロファイルを持たないカスタムアカウントを使った、(2) LocalSystem, NetworkServce などを使った、(3) ApplicationPoolIdentity を使ったが詳細設定で[ユーザープロファイルの読み込み]を False に設定した場合です。

その場合、%temp% は C:\Windows\Temp になるそうです (未検証・未確認)。 自分の環境でそのフォルダのプロパティを開いてセキュリティを見ると以下のようになっています。

C:\Windows\Temp のセキュリティ

IIS_IUSRS は IIS のワーカープロセスのアカウントが属するグループ、Users は IUSR が属するグループですが、書き込み・読み出し権限は設定されてません。したがって、このフォルダーに書き込みに行けば権限がないので失敗するということになります。

想像ですが、Microsoft Q&A の質問者さんのケースで 64KB を超えるファイルアップロードに失敗したのは、アプリケーションプールの Identity がユーザープロファイルを持たないからではなかろうかと思います。

最後にもう一つ。ASP.NET Core アプリを IIS でホストする場合、インプロセスとアウトプロセスという方法があります。

インプロセス ホスティング モデル

インプロセス ホスティング モデル

アウトプロセス ホスティング モデル

アウトプロセス ホスティング モデル

いずれの場合でも、アプリケーションプールの Identity が ASPNETCORE_TEMP またはユーザーの一時フォルダ��に対する書き込み・読み取り権限を持っていなければならないのは同じです。(アウトプロセスホスティングモデルの場合、w3wp.exe で動く ASP.NET Core Module が donet.exe を起動するので)

Tags: , ,

Upload Download

応答ヘッダが 64KB を超えるとエラー

by WebSurfer 2. September 2019 12:00

HttpClient を使った HPPT 通信で、応答ヘッダが 64KB を超えると WebException 例外がスローされるという話を備忘録として書いておきます。

(元の話は Teratail のスレッド「GetAsync処理時のメッセージの長さが制限の解消方法について」のもので、実際に自分が経験した訳ではなく聞いた話です)

同様な問題は HttpWebResponse / HttpWebRequest を使った時から起こっていた問題だそうで、応答ヘッダが 64KB を超えると WebException がスローされ、以下のエラーメッセージが出るそうです。

"接続が切断されました: メッセージの長さが制限を超えています。"

英文では、

"The underlying connection was closed: The message length limit was exceeded."

応答ヘッダが 64KB を超えるというのはレアなのか、日本語のエラーメッセージでググっても参考になる記事はヒットしませんでした。

でも、英語圏まで検索範囲を広げる(英文でググる)と HttpWebResponse / HttpWebRequest でこの問題に遭遇した人はいるようで、WebException: "The message length limit was exceeded" 他の記事がヒットします。

その記事に書いてある解決策は、HttpWebRequest の MaximumResponseHeadersLength プロパティを -1 (無制限) に設定することだそうです。(未検証・未確認です)

HttpClient を使う場合は、.NET Framework 4.7.1 以降ですが、HttpClientHandler クラスMaxResponseHeadersLength プロパティを使って応答ヘッダのサイズの許容最大値を設定できるそうです。

// Create an HttpClientHandler object
HttpClientHandler handler = new HttpClientHandler();
handler.MaxResponseHeadersLength = 128;  // 128KB

// Create an HttpClient object
HttpClient client = new HttpClient(handler);

.NET 4.5 では MaxResponseHeadersLength プロパティは使えず .NET 4.7.1 で使えるようになったということは、HttpWebRequest / HttpWebResponse で起こっていた問題に対応できないことを指摘されて追加したのかもしれませんね。(想像です)

Tags: , , ,

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。ブログ2はそれ以外の日々の出来事などのトピックスになっています。

Calendar

<<  February 2026  >>
MoTuWeThFrSaSu
2627282930311
2345678
9101112131415
16171819202122
2324252627281
2345678

View posts in large calendar