当内容长度超过 64k 时,将二进制数据流式传输到 WCF Rest 服务会产生错误请求 (400)

发布于 2024-10-11 04:03:10 字数 3112 浏览 2 评论 0原文

我有一个采用流的 WCF 服务:

[ServiceContract]
public class UploadService : BaseService
{
    [OperationContract]
    [WebInvoke(BodyStyle=WebMessageBodyStyle.Bare, Method=WebRequestMethods.Http.Post)]
    public void Upload(Stream data)
    {
        // etc.         
    }
}

此方法允许我的 Silverlight 应用程序上传大型二进制文件,最简单的方法是从客户端手动制作 HTTP 请求。下面是 Silverlight 客户端中执行此操作的代码:

const int contentLength = 64 * 1024;  // 64 Kb

var request = (HttpWebRequest)WebRequest.Create("http://localhost:8732/UploadService/");
request.AllowWriteStreamBuffering = false;
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/octet-stream";
request.ContentLength = contentLength;
using (var outputStream = request.GetRequestStream())
{
     outputStream.Write(new byte[contentLength], 0, contentLength);
     outputStream.Flush();
     using (var response = request.GetResponse());
}

现在,在上面的情况下,我正在传输 64 kB 的数据(或更少),此工作正常,并且如果我在我的WCF 方法,我可以检查流并看到 64 kB 的零 - 耶!

如果我发送超过 64 kB 的数据,就会出现问题,例如将客户端代码的第一行更改为以下内容:

const int contentLength = 64 * 1024 + 1; // 64 kB + 1 B

现在,当我调用 request.GetResponse 时,会在客户端上引发异常():

远程服务器返回错误: (400) 错误请求。

在服务器的WCF配置中,我已将maxReceivedMessageSize、maxBufferSize和maxBufferPoolSize设置为2147483647,但无济于事。以下是我的服务的 app.config 中的相关部分:

<service name="UploadService">
    <endpoint address="" 
              binding="webHttpBinding" 
              bindingName="StreamedRequestWebBinding"
              contract="UploadService" 
              behaviorConfiguration="webBehavior">
        <identity>
            <dns value="localhost" />
        </identity>
    </endpoint>
    <host>
        <baseAddresses>
            <add baseAddress="http://localhost:8732/UploadService/" />
       </baseAddresses>
    </host>       
</service>

<bindings>
    <webHttpBinding>
        <binding name="StreamedRequestWebBinding" 
                 bypassProxyOnLocal="true"
                 useDefaultWebProxy="false"
                 hostNameComparisonMode="WeakWildcard"
                 sendTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:05:00"
                 maxReceivedMessageSize="2147483647"
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 transferMode="StreamedRequest">
            <readerQuotas maxArrayLength="2147483647"
                          maxStringContentLength="2147483647" />
        </binding>
    </webHttpBinding>
</bindings>

<behaviors>
    <endpointBehaviors>
        <behavior name="webBehavior">
            <webHttp />
        </behavior>
    <endpointBehaviors>
</behaviors>

如何使我的服务接受超过 64 kB 的流式发布数据?

编辑:如上面的客户端代码所示,我没有使用服务引用,而是手动构建 HTTP 请求。 (这是因为 Silverlight 服务引用不支持流。)

I have a WCF service that takes a stream:

[ServiceContract]
public class UploadService : BaseService
{
    [OperationContract]
    [WebInvoke(BodyStyle=WebMessageBodyStyle.Bare, Method=WebRequestMethods.Http.Post)]
    public void Upload(Stream data)
    {
        // etc.         
    }
}

This method is to allow my Silverlight application to upload large binary files, the easiest way being to craft the HTTP request by hand from the client. Here is the code in the Silverlight client that does this:

const int contentLength = 64 * 1024;  // 64 Kb

var request = (HttpWebRequest)WebRequest.Create("http://localhost:8732/UploadService/");
request.AllowWriteStreamBuffering = false;
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/octet-stream";
request.ContentLength = contentLength;
using (var outputStream = request.GetRequestStream())
{
     outputStream.Write(new byte[contentLength], 0, contentLength);
     outputStream.Flush();
     using (var response = request.GetResponse());
}

Now, in the case above, where I am streaming 64 kB of data (or less), this works OK and if I set a breakpoint in my WCF method, and I can examine the stream and see 64 kB worth of zeros - yay!

The problem arises if I send anything more than 64 kB of data, for instance by changing the first line of my client code to the following:

const int contentLength = 64 * 1024 + 1; // 64 kB + 1 B

This now throws an exception on the client when I call request.GetResponse():

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

In the server's WCF configuration I have set maxReceivedMessageSize, maxBufferSize and maxBufferPoolSize to 2147483647, but to no avail. Here are the relevant sections from my service's app.config:

<service name="UploadService">
    <endpoint address="" 
              binding="webHttpBinding" 
              bindingName="StreamedRequestWebBinding"
              contract="UploadService" 
              behaviorConfiguration="webBehavior">
        <identity>
            <dns value="localhost" />
        </identity>
    </endpoint>
    <host>
        <baseAddresses>
            <add baseAddress="http://localhost:8732/UploadService/" />
       </baseAddresses>
    </host>       
</service>

<bindings>
    <webHttpBinding>
        <binding name="StreamedRequestWebBinding" 
                 bypassProxyOnLocal="true"
                 useDefaultWebProxy="false"
                 hostNameComparisonMode="WeakWildcard"
                 sendTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:05:00"
                 maxReceivedMessageSize="2147483647"
                 maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 transferMode="StreamedRequest">
            <readerQuotas maxArrayLength="2147483647"
                          maxStringContentLength="2147483647" />
        </binding>
    </webHttpBinding>
</bindings>

<behaviors>
    <endpointBehaviors>
        <behavior name="webBehavior">
            <webHttp />
        </behavior>
    <endpointBehaviors>
</behaviors>

How do I make my service accept more than 64 kB of streamed post data?

Edit: as shown in the client code above, I am not using service references, rather constructing the HTTP request by hand. (This is because Silverlight service references do not support streams.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泪痕残 2024-10-18 04:03:10

所以我发现问题 - bindingName="StreamedRequestWebBinding" 应该是 bindingConfiguration="StreamedRequestWebBinding"。对于前者,我指定的绑定配置根本没有被使用,因此 maxReceivedMessageSize 默认为 64kB。

So I found the problem - bindingName="StreamedRequestWebBinding" should be bindingConfiguration="StreamedRequestWebBinding". With the former, my the binding configuration specified was not being used at all, so maxReceivedMessageSize defaulted to 64kB.

若能看破又如何 2024-10-18 04:03:10

您的 Silverlight 应用程序中还有一个 ServiceReferences.ClientConfig 文件,您应该更新该配置中的 maxBufferSizemaxReceivedMessageSize

There is a ServiceReferences.ClientConfig file in your Silverlight app as well, you should update the maxBufferSize and maxReceivedMessageSize in that config.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文