Liran Friedman
Liran Friedman

Reputation: 4287

wcf stream length = 0 when sending stream to upload file

I've looked at many solutions but none helped to solve this issue.

I have a wcf service that is supposed to use for file upload.

Since I want to upload large files I'm not using WebHttpRequest, I've added a service reference for the wcf and I'm using it instead.

here is the service interface:

[ServiceContract(Namespace = "https://Services.XXX.com", ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
public interface IAttachmentService
{
    [OperationContract]
    [WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "UploadFile", Method = "POST", ResponseFormat = WebMessageFormat.Json)]
    string UploadFile(Stream file);
}

and here is how I'm sending the stream:

using (MemoryStream stream = new MemoryStream())
{
    //write some data to the the memory stream
    stream.Write(len, 0, len.Length);
    stream.Write(jsonFileBytes, 0, jsonFileBytes.Length);

    //write the file data to the memory stream
    while ((bytesReadCount = file.Read(bufferRead, 0, bufferRead.Length)) > 0)
    {
        stream.Write(bufferRead, 0, bytesReadCount);
    }

    stream.Position = 0;

    byte[] array = stream.ToArray();

    WCFClientProxy<Attachment.Interfaces.IAttachmentService> proxy = new WCFClientProxy<Attachment.Interfaces.IAttachmentService>();
    return Serialization.ConvertToJson(new { IsError = false, Files = proxy.Instance.UploadFile(array) });
}

but on the method that receives the stream in order to save the file the streams length is 0

I've also tryied to send byte[] like this:

using (MemoryStream stream = new MemoryStream())
{
    //write some data to the the memory stream
    stream.Write(len, 0, len.Length);
    stream.Write(jsonFileBytes, 0, jsonFileBytes.Length);

    //write the file data to the memory stream
    while ((bytesReadCount = file.Read(bufferRead, 0, bufferRead.Length)) > 0)
    {
        stream.Write(bufferRead, 0, bytesReadCount);
    }

    stream.Position = 0;

    byte[] array = stream.ToArray();

    WCFClientProxy<Attachment.Interfaces.IAttachmentService> proxy = new WCFClientProxy<Attachment.Interfaces.IAttachmentService>();
    return Serialization.ConvertToJson(new { IsError = false, Files = proxy.Instance.UploadFile(array) });
}

but with this approach I'm getting this error:

The remote server returned an unexpected response: (400) Bad Request.

Upvotes: 1

Views: 1415

Answers (2)

Liran Friedman
Liran Friedman

Reputation: 4287

I solved it.

  1. remove the [WebInvoke...] and leave only the [OperationContract] in the interface
  2. Use these config files

Client config:

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="2147483647" />
  </system.web>

  <system.serviceModel>
    <bindings>
      <webHttpBinding>

        <binding name="WebHttpBinding_IAttachmentService" closeTimeout="10:00:00" openTimeout="10:00:00" receiveTimeout="10:00:00" sendTimeout="10:00:00"
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 maxReceivedMessageSize="2147483647">

          <readerQuotas maxDepth="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647"
                        maxStringContentLength="2147483647"/>

          <security mode="None" />
        </binding>
      </webHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:54893/AttachmentService.svc"
                binding="webHttpBinding"
                bindingConfiguration="WebHttpBinding_IAttachmentService"
                behaviorConfiguration="webHttpBehavior"
                contract="XXX.Interfaces.IAttachmentService" />
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webHttpBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="1073741824" />
      </requestFiltering>
    </security>
  </system.webServer>

Service config:

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="2147483647" executionTimeout="3600" />
  </system.web>

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>
      <service name="XXX.Implementation.AttachmentService">
        <endpoint binding="webHttpBinding"
                  behaviorConfiguration="webHttpBehavior"
                  bindingConfiguration="higherMessageSize"
                  contract="XXX.Interfaces.IAttachmentService" />
      </service>
    </services>
    <bindings>
      <webHttpBinding>
        <binding name="higherMessageSize" transferMode="Streamed" closeTimeout="10:00:00" openTimeout="10:00:00" receiveTimeout="10:00:00" sendTimeout="10:00:00"
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 maxReceivedMessageSize="2147483647">

          <readerQuotas maxDepth="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647"
                        maxStringContentLength="2147483647"/>

          <security mode="None"/>
        </binding>
      </webHttpBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webHttpBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule"/>
    </modules>
     <handlers>
         <remove name ="WebDAV"/>
    </handlers>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="2147483647" />
      </requestFiltering>
    </security>
  </system.webServer>

Upvotes: 0

Justin Killen
Justin Killen

Reputation: 737

Take out the using(). Your memory stream is going out of scope before the upload starts/completes.

Upvotes: 1

Related Questions