WCF: Streaming Large Data Files Using WebHttpBinding

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:

Deutsch (de-DE)

Brazilian Portuguese (pt-BR)

Sort by: Published Date | Most Recent | Most Useful
Comments
Page 1 of 1 (1 items)