C# – file upload download using WCF rest

cnetrestwcf

I am using .net 4.0 and trying to upload a file using a rest wcf service with a method called upload and download it using the same rest service using a method called download. There is a console application that sends the stream data to the wcf service and the same console app downloads from the service. The console application uses WebChannelFactory to connect and work with the service.

Here is a code from the console app

            StreamReader fileContent = new StreamReader(fileToUpload, false);
            webChannelServiceImplementation.Upload(fileContent.BaseStream );

This is the wcf service code

public void Upload(Stream fileStream)
{
        long filebuffer  = 0;
        while (fileStream.ReadByte()>0)
        {
            filebuffer++;
        }

        byte[] buffer = new byte[filebuffer];
        using (MemoryStream memoryStream = new MemoryStream())
        {
            int read;

            while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                memoryStream.Write(buffer, 0, read);

            }
            File.WriteAllBytes(path, buffer);
        }
}

Now at this step when I examine the file, I notice it has the same size in Kilobytes as the original file that was sent from the console app, but when I open the file, it has no content. The file can be any file type, be it an excel or word document, it still comes up to the server as an empty file. Where is all the data gone?

The reason I am doing a fileStream.ReadByte()>0 is because I read somewhere that when transfering over the network, the buffer length cant be found out (which is why I was getting an exception when trying to get the length of the stream in the service upload method). This is why I dont use byte[] buffer = new byte[32768]; as in shown in many online examples where the byte array is fixed.

While downloading from the service I use this code on the wcf service side

    public Stream Download()
    {
        return new MemoryStream(File.ReadAllBytes("filename"));
    }

And on the console app side I have

        Stream fileStream = webChannelServiceImplementation.Download();

        //find size of buffer
        long size= 0;
        while (fileStream .ReadByte() > 0)
        {
            size++;
        }
        byte[] buffer = new byte[size];

        using (Stream memoryStream = new MemoryStream())
        {
            int read;
            while ((read = fileContents.Read(buffer, 0, buffer.Length)) > 0)
            {
                memoryStream.Write(buffer, 0, read);
            }

            File.WriteAllBytes("filename.doc", buffer);
        }

Now this downloaded file is also blank, because its downloading the file I uploaded earlier using the upload code above, and its only 16 KB in size even though the uploaded file was 200 KB in size.

What is wrong with my code? Any help appreciated.

Best Answer

You can make this far simpler:

public void Upload(Stream fileStream)
{
    using (var output = File.Open(path, FileMode.Create))
        fileStream.CopyTo(output);
}

The problem with your existing code is that you call ReadByte and read the entire input stream, then try to read it again (but it's now at the end). This means your second reads will all fail (the read variable will be 0 in your loop, and immediately break out) since the stream is now at its end.