0

I'm trying to implement file upload into my WCF Service in asp .net C#

Here is the code in WCF Server for File uploading.

 public void FileUpload(string fileName, Stream fileStream)
       {
           FileStream fileToupload = new FileStream("D:\\FileUpload\\" + fileName, FileMode.Create);

        //   byte[] bytearray = new byte[10000];
           byte[] bytearray = new byte[1000];
           int bytesRead, totalBytesRead = 0;
           do
           {
               bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
               totalBytesRead += bytesRead;
               if(bytesRead > 0)
               fileToupload.Write(bytearray, 0, bytearray.Length);

           } while (bytesRead > 0);

         //  fileToupload.Write(bytearray, 0, bytearray.Length);
           fileToupload.Close();
           fileToupload.Dispose();



       }

Here is the code for Client to upload a File: (Fixed Byte Array Size)

protected void bUpload_Click(object sender, EventArgs e)
{
    byte[] bytearray = null;
    Stream stream;
    string fileName = "";
    //throw new NotImplementedException();
    if (FileUpload1.HasFile)
    {
        fileName = FileUpload1.FileName;
        stream = FileUpload1.FileContent;
        stream.Seek(0, SeekOrigin.Begin);
        bytearray = new byte[stream.Length];
        int count = 0;
        while (count < stream.Length)
        {
            bytearray[count++] = Convert.ToByte(stream.ReadByte());
        }

    }

    string baseAddress = "http://localhost/WCFService/Service1.svc/FileUpload/";

    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(baseAddress + fileName);
    request.Method = "POST";
    request.ContentType = "text/plain";
    Stream serverStream = request.GetRequestStream();
    serverStream.Write(bytearray, 0, bytearray.Length);
    serverStream.Close();
    try
    {
        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
        {
            int statusCode = (int)response.StatusCode;
            System.Diagnostics.Debug.WriteLine("statusCode: " + statusCode);

            StreamReader reader = new StreamReader(response.GetResponseStream());
            System.Diagnostics.Debug.WriteLine("reader: " + reader.ToString());

        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("--- EXCEPTION ---");
        ex.ToString();
    }
}

This is working good with a small size file, When I tried with bigger size files I changed fixed size byte array to a dynamic byte array Writing to stream. Here is updated code: (chunks of 1024 bytes of Byte array used to Send data)

        request.Method = "POST";
        request.ContentType = "text/plain";
       // Stream serverStream = request.GetRequestStream();

        if (FileUpload1.HasFile)
        {
            fileName = FileUpload1.FileName;
            stream = FileUpload1.FileContent;
            stream.Seek(0, SeekOrigin.Begin);
            bytearray = new byte[1024];//stream.Length];


        }
        int TbyteCount = 0;
        Stream requestStream = request.GetRequestStream();

            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
            int byteCount = 0;
            while ((byteCount = stream.Read(buffer, 0, bufferSize)) > 0)
            {
                TbyteCount = TbyteCount + byteCount; 
                requestStream.Write(buffer, 0, byteCount);
            }

            requestStream.Close();


        try
        {
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                int statusCode = (int)response.StatusCode;
                System.Diagnostics.Debug.WriteLine("statusCode: " + statusCode);

                StreamReader reader = new StreamReader(response.GetResponseStream());
                System.Diagnostics.Debug.WriteLine("reader: " + reader.ToString());

            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("--- EXCEPTION ---");
            ex.ToString();
        }
    }

But While reading response I get Exception The remote server returned an error: (413) Request Entity Too Large.

Am I doing correct with writing multiple times in request stream !?

I used a file size 22.4 KB, it is successfully uploaded using 1st code (fixed size array) If I split file size in multiples of 1024 bytes and tried to send then there is a problem.

Web.config file

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
  </appSettings>
  <system.web>
    <compilation debug="true"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WcfServiceApp.Service1" behaviorConfiguration="ServiceBehavior">
        <endpoint address="" binding="webHttpBinding" contract="WcfServiceApp.IService1" behaviorConfiguration="webBehaviour"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:50327/Service1.svc"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webBehaviour">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <!--<protocolMapping>
      <add binding="basicHttpsBinding" scheme="https"/>
    </protocolMapping>-->
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept"/>
      </customHeaders>
    </httpProtocol>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>
Ashok
  • 601
  • 1
  • 17
  • 32
  • http://stackoverflow.com/questions/10122957/iis7-413-request-entity-too-large-uploadreadaheadsize – dremerDT Oct 13 '15 at 12:01
  • Thanks for the comment. I used a file size 22.4 KB, it is successfully uploaded using 1st code (fixed size array) If I split file size in multiples of 1024 bytes and tried to send then there is a problem. – Ashok Oct 13 '15 at 12:29
  • You don't appear to be sending the data to the service in chunks - you're building the stream in chunks, but you're sending it as one request. Can you post your service's binding configuration (the whole `` section of the config, preferably). Chances are you either didn't create a specific binding or did not assign said binding to an explicit endpoint. – Tim Oct 14 '15 at 05:50
  • @Tim I'm sending in chunk using a while loop and requestStream.Write(buffer, 0, byteCount); I have edit/updated web.config file in main question. Thanks for the comment – Ashok Oct 14 '15 at 06:17

2 Answers2

1

In Your Service bindings, Increase the reader quota. Read more about each setting here https://msdn.microsoft.com/en-us/library/ms731325(v=vs.110).aspx. Aslo look into this https://msdn.microsoft.com/en-us/library/system.servicemodel.basichttpbinding.maxreceivedmessagesize(v=vs.100).aspx

Shetty
  • 1,792
  • 4
  • 22
  • 38
  • I think the problem is in Sending chunks of data, multiple of 1024 bytes. I have updated the question. – Ashok Oct 13 '15 at 12:34
1

When you try to transfer big serialized object with some structure this problem usually caused by leak of maxItemsInObjectGraph in configuration. See my answer here

But in your case you try just transfer simple data file as stream of bytes. To do that via webHttpBinding you should specify proper service contract, which accepts only stream message as input. All additional stuff like filenames you can specify as headers in message contract (actually maybe you way with filename as parameter from URI will also work). Then you must set TransferMode = TransferMode.Streamed for your binding. Some code example is here One more with config samples is here.

Keywords for additional googling is webhttpbinding streaming

Community
  • 1
  • 1
Mimas
  • 525
  • 3
  • 7