Search code examples
c#wcfwcf-binding

WCF Stream-Service push data to client


I am currently working on a task to transfer a large byte array with wcf.

I tried following code and it works:

On the server side:

[OperationContract]
public System.IO.Stream GetData()
{
    FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
    return fs;
}

On the client side:

public void GetFile()
    {
        IByteService byteService = channelFactory.CreateChannel();
        Stream serverStream = byteService.GetData();

        byte[] buffer = new byte[2048];
        int bytesRead;

        FileStream fs = new FileStream(filePath, FileMode.CreateNew);

        while ((bytesRead = serverStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            fs.Write(buffer, 0, bytesRead);
        }
    }

But the other way around it does not work:

On the server side:

  [OperationContract]
   public void WriteToStream(Stream clientStream)
        {   
         FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
         fs.CopyTo(clientStream);
        }

On the client side:

public void SendStream()
{
    FileStream bytesReceivedFromTheServerAsFile = new FileStream(filePath,FileMode.OpenOrCreate);
    IByteService byteService = channelFactory.CreateChannel();

    byteService.WriteToStream(bytesReceivedFromTheServerAsFile);
}

fs.CopyTo(stream) throws NotSupportedException on the server side.

Would like to know why?

I would like to do the download other way around because on the server side I do not have a stream. I will receive bytes from a third party lib. So i was thinking to do it like this:

On the server side:

    [OperationContract]
   public void WriteToStream(Stream clientStream)
        {   
            byte[] buffer = new byte[2048]; // read in chunks of 2KB
            int bytesRead = 100;
            while ((ThirdPartyClass.GetNextBytes(buffer))
{
             clientStream.Write(buffer, 0, bytesRead);  
            }

        }

On the client side:

    public void SendStream()
    {
        FileStream bytesReceivedFromTheServerAsFile = new FileStream(filePath, FileMode.OpenOrCreate);
        IByteService byteService = channelFactory.CreateChannel();

        byteService.WriteToStream(bytesReceivedFromTheServerAsFile);
    }

Because i dont have a stream on the server side. I was thinking the other way around to push the data to the client will be a nice approach. However, other soulution concepts would be great.


Solution

  • WCF does not support pushing stream data like that. Remember that client and server are in separate memory spaces. The server can never access objects that the client has. When you return a stream WCF constructs the illusion for the client that the stream the client reads from is what the server returned. WCF cannot do this the other way around.

    Write yourself a custom stream that reads from the 3rd party class. Return that stream from the server.