ファイルのアップロードのプロトタイプを作成するための単純な WCF サービスを作成しました。サービス:
[ServiceContract]
public class Service1
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/Upload")]
public void Upload(Stream stream)
{
using (FileStream targetStream = new FileStream(@"C:\Test\output.txt", FileMode.Create, FileAccess.Write))
{
stream.CopyTo(targetStream);
}
}
}
「Streamed」に設定して使用webHttpBinding
し、すべて2GBに設定します。10MBに設定しました。transferMode
maxReceivedMessageSize
maxBufferPoolSize
maxBufferSize
httpRuntime
maxRequestLength
クライアントは、次の方法で HTTP 要求を発行します。
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(@"http://.../Service1.svc/Upload");
request.Method = "POST";
request.SendChunked = true;
request.AllowWriteStreamBuffering = false;
request.ContentType = MediaTypeNames.Application.Octet;
using (FileStream inputStream = new FileStream(@"C:\input.txt", FileMode.Open, FileAccess.Read))
{
using (Stream outputStream = request.GetRequestStream())
{
inputStream.CopyTo(outputStream);
}
}
さて、最後に、何が問題なのですか:
100MB のファイルをアップロードすると、サーバーは HTTP 400 (Bad request) を返します。WCF トレースを有効にしようとしましたが、エラーは表示されません。増やすとhttpRuntime
。maxRequestLength
1GB まで、ファイルは問題なくアップロードされます。MSDN によると、maxRequestLength
「入力ストリームのバッファリングしきい値の制限を KB 単位で指定します」。
これにより、ファイル全体(100MBすべて)が最初に「入力ストリームバッファー」に保存され、Upload
サーバー上のメソッドでのみ使用できるようになると思います。実際、サーバー上のファイルのサイズが (予想どおり) 徐々に増加するのではなく、ファイルが作成された時点で既に 100MB の大きさになっていることがわかります。
質問:「入力ストリーム バッファ」が適度に小さく (たとえば 1MB)、オーバーフローしたときにUpload
メソッドが呼び出されるようにするにはどうすればよいでしょうか? 言い換えれば、ファイル全体をどこにもバッファリングすることなく、アップロードを真にストリーミングしたいのです。
編集:httpRuntime
ここに関連する別の設定が含まれ
ていることを発見しました - requestLengthDiskThreshold
。入力バッファがこのしきい値を超えて大きくなると、メモリではなくファイルシステムに保存されるようです。したがって、少なくとも 100MB の大きなファイル全体がメモリに保持されません (これが私が最も恐れていたことです) が、このバッファを完全に回避する方法があるかどうかを知りたいです。