Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

How to Download a Large File from a WCF Service?

3.58/5 (8 votes)
12 Mar 2014CPOL3 min read 25.1K  
How to download a large file from a WCF service

While reading WCF technical forums, I have come across the following questions a number of times:

  • How to download a large file from a WCF Service?
  • I am getting an error while transferring a large file from WCF service to client?
  • How to send large messages or data from WCF Service to a client?

So, I decided to write a simple WCF Tutorial on this topic with possible approaches to answer the above questions. I'll follow a step by step method to provide a complete solution as follows:

So, we will try to understand the problem that is involved with downloading a large file from a WCF service. For the purpose of implementation, we will create a simple WCF Service that returns a byte array.

  1. First of all, let's create a WCF service contract IMyBookService that returns a Book.
    C#
    public interface IMyBookService
    {
       [OperationContract]
       Book DownloadBook();
    }

    Book DataContract has multiple members, i.e., Title, ISBN, Author and Data (a byte array).

    C#
    [DataContract]
    public class Book
    {
            [DataMember]
            public string Title { get; set; }
    
            [DataMember]
            public string ISBN { get; set; }
    
            [DataMember]
            public string Author { get; set; }
    
            [DataMember]
            public byte[] Data { get; set; }
    }
  2. Implementation of IMyBookService is as follows:
    C#
    public class MyBookService : IMyBookService
        {
            Book IMyBookService.DownloadBook()
            {
                Book myBook = new Book();
                myBook.Title = "WCF RESTful Service";
                myBook.ISBN = "178-3-15-146510-0";
                myBook.Author = "Imran Abdul Ghani";
                myBook.Data = File.ReadAllBytes(@"D:\MyBooks\WCF RESTful Service.doc"); 
    
                return myBook;
            }
        }
  3. Configuration settings for the service is given below:
    XML
    <services>
       <service name="BookService.MyBookService" behaviorConfiguration="serviceBehavior">
                <endpoint address=""MyBookService"
                                 Binding = "wsHttpBinding" bindingConfiguration = "wsBindingConfig"
                                 Contract = "BookService.IMyBookService" />
                 <host>
                          <add baseAddress="http://localhost:9999" />
                 </host>
       </service>
    </services>
    <bindings>
          <wsHttpBinding>
                   <binding name="wsBindingConfig" messageEncoding="Text" />
         </wsHttpBinding>
    </bindings>

In order to consume the service, the client side code will be as follows:

C#
BookService.MyBookServiceClient client = new BookService.MyBookServiceClient();
client.Book myBook = client.DownloadBook();
File.WriteAllBytes(@"D:\MyDownloadedBooks\" + myBook.Title, myBook.Data);

When we call the download method of MyBookService through client code, it will generate the following exception:

"Maximum message size quota for incoming messages (65536) has been exceeded...."

So, we have reached at a point that how a WCF service behaves by default for such scenarios. One thing is obvious from the above error message that Maximum message size for downloading a file in WCF, by default, is around 65K. In order to handle this issue, simply increase the value of two configuration settings:

  • maxReceivedMessageSize
  • readerQuotas

So, updated bindingConfiguration will be as follows:

XML
<bindings>
   <wsHttpBinding>
          <binding name="wsBindingConfig"
                                       maxReceivedMessageSize="10000000"
                                       messageEncoding="Text">
                    <readerQuotas maxArrayLength="1000000" />
          </binding>
 </wsHttpBinding>
</bindings>

Now, if we run the above code, it will work fine and the file will be successfully downloaded. Cheers...

Although we got the answer to questions asked at the start of this WCF Service tutorial, this approach has some disadvantages with respect to performance.

  • As we have seen, we are using default messageEncoding i.e. "Text". Text encoding uses base 64 encoding format. Base 64 encoded files are normally larger than the original file size, so further increasing the file size to approximately 30% unnecessarily.
  • Also there is a cost for encoding at one end and decoding on the other.

In order to do the same, we have a better approach and that is to use MTOM (Message Transmission Optimization Mechanism) message encoding. We just need to replace MTOM in the above binding configuration instead of Text.

XML
<bindings>
   <wsHttpBinding>
         <binding name="wsBindingConfig"
                                      maxReceivedMessageSize="10000000"
                                      messageEncoding="Mtom">
                        <readerQuotas maxArrayLength="1000000" />
        </binding>
   </wsHttpBinding>
</bindings>

Using MTOM message encoding format has advantages listed below:

  • It keeps the size of message under control.
  • Interoperable because it's based on Open specification.

Hopefully, this simple WCF article will be helpful in answering the above mentioned questions. Further, I am planning to write another Tutorial on "How to upload large data to a WCF Service?" later this month. So, be in touch and enjoy service programming.

Reader of this article might also be interested in:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)