WCF: Streaming Large Data Files Using WebHttpBinding
This example code streams large data files using [[Windows Communication Foundation]] (WCF) and the WebHttpBinding.
[The original code comes from this forum post: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/fb9efac5-8b57-417e-9f71-35d48d421eb4 ]
For more information about streaming, see http://msdn.microsoft.com/en-us/library/ms733742.aspx.
public class Post_fb9efac5_8b57_417e_9f71_35d48d421eb4
{
[ServiceContract]
public interface ITest
{
[OperationContract]
[WebGet]
Stream DownloadFile(string fileName);
[OperationContract]
[WebInvoke(UriTemplate = "/UploadFile/{fileName}")]
void UploadFile(string fileName, Stream fileContents);
}
static long CountBytes(Stream stream)
{
byte[] buffer = new byte[100000];
int bytesRead;
long totalBytesRead = 0;
do
{
bytesRead = stream.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);
return totalBytesRead;
}
class MyReadonlyStream : Stream
{
long length;
long leftToRead;
public MyReadonlyStream(long length)
{
this.length = length;
this.leftToRead = length;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override void Flush()
{
}
public override long Length
{
get { return this.length; }
}
public override long Position
{
get { throw new NotSupportedException(); }
set { throw new NotSupportedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
int toReturn = (int)Math.Min(this.leftToRead, (long)count);
this.leftToRead -= toReturn;
return toReturn;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
}
public class Service : ITest
{
public Stream DownloadFile(string fileName)
{
WebOperationContext.Current.OutgoingResponse.Headers["Content-Disposition"] = "attachment; filename=" + fileName;
return new MyReadonlyStream(200000000); //200MB
}
public void UploadFile(string fileName, Stream fileContents)
{
long totalBytesRead = CountBytes(fileContents);
Console.WriteLine("Total bytes read for file {0}: {1}", fileName, totalBytesRead);
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
WebHttpBinding binding = new WebHttpBinding
{
TransferMode = TransferMode.Streamed,
MaxReceivedMessageSize = int.MaxValue,
};
binding.ReaderQuotas.MaxArrayLength = int.MaxValue;
host.AddServiceEndpoint(typeof(ITest), binding, "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/DownloadFile?fileName=test.txt");
req.Method = "GET";
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
foreach (string header in resp.Headers.AllKeys)
{
Console.WriteLine("{0}: {1}", header, resp.Headers[header]);
}
Stream respStream = resp.GetResponseStream();
long size = CountBytes(respStream);
Console.WriteLine("Response size: {0}", size);
req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/UploadFile/test.txt");
req.Method = "POST";
req.SendChunked = true;
req.AllowWriteStreamBuffering = false;
req.ContentType = "application/octet-stream";
Stream reqStream = req.GetRequestStream();
byte[] buffer = new byte[10000000];
long bytesWritten = 0;
for (int i = 0; i < 50; i++)
{
reqStream.Write(buffer, 0, buffer.Length);
bytesWritten += buffer.Length;
if ((i % 10) == 0)
{
Console.WriteLine("Wrote {0} bytes", bytesWritten);
}
}
reqStream.Close();
resp = (HttpWebResponse)req.GetResponse();
Console.WriteLine(resp.StatusCode);
}
}
See Also
Other Languages
This article is also available in the following languages: