IIS 7/7.5 を使用しています。ユーザーが巨大なデータをアップロードできるページがあります。POST 本文を読む必要がある場合とそうでない場合があります。IIS/ASP.NET で、通知するまで POST エンティティ本体の読み取りを延期する方法はありますか。
1 に答える
ファイル サイズを気にせずに、リクエスト ヘッダーを安全に読み取ることができます。詳しく説明しましょう。/upload.aspx
エンドポイントにファイルをアップロードできる次の html ページを検討してください。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<form action="/upload.ashx" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<button type="submit">OK</button>
</form>
</body>
</html>
次に、汎用ハンドラーを作成できます。
public class Upload: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var request = context.Request;
var response = context.Response;
response.ContentType = "text/plain";
response.Write(request.Headers.ToString());
}
public bool IsReusable
{
get { return true; }
}
}
次に、巨大なファイルをアップロードできるようにするために、web.config で要求の制限を増やしたことを確認します。
<httpRuntime maxRequestLength="10485760" />
と:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>
ここで、ユーザーがアップロードする非常に大きなファイル (たとえば 5GB) を選択し、送信ボタンを押したとします。汎用ハンドラーのProcessRequest
メソッドはすぐにヒットするため、ヘッダーに非常にすばやくアクセスできます。
public void ProcessRequest(HttpContext context)
{
var fileSize = context.Request.ContentLength;
}
このファイルの内容を読みたい場合は、ファイルの入力ストリームから読み始めることができます。これは、ファイル全体がアップロードされるまで明らかに時間がかかります。
public void ProcessRequest(HttpContext context)
{
// We reach at that point pretty fast and we can read the headers here
// and determine for example the total bytes to be uploaded
var fileSize = context.Request.ContentLength;
// now we can start reading the file which would obviously take quite a lot of time:
context.Request.Files[0].InputStream.Read(...)
}
しかし、あなたは自問するかもしれません:ProcessRequest
メソッドは、ユーザーが送信ボタンを押した直後にヒットします。その時点でアップロードされたファイルはどこにありますか? 実際、クライアントからバイトが到着すると、IIS はそれらを一時ファイルにチャンクし (メモリ内にないため、心配する必要はありません)、InputStream はこの場所を指しているため、そこから読み取りを開始すると、実際にはIIS がクライアントから既に受信し、利用できるようにしたデータを読み取ります。これらの一時ファイルは、入力ストリームからの読み取りを開始するときに作成されます。このストリームから読み取るときは、データをメモリにロードしているため、注意が必要です。したがって、クライアントから非常に大きなデータが送られる可能性がある場合は、常にチャンクで読み取って処理する必要があります。Stream.CopyTo
方法)。