PHP 到带有 SoapClient 的 WCF - 请求实体太大
PHP to WCF with SoapClient - Request Entity Too Large
我有一个 soap svc 网络服务,这些是我的 WS 方法:
StoreService.svc.cs
namespace StoreServices
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class StoreService : IStoreService
{
public bool SaveCarData(Car car)
{
//Some code
}
}
}
IStoreService.cs
namespace StoreServices
{
[ServiceContract]
public interface IStoreService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/SaveCarData", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
bool SaveCarData(Car car);
}
}
在我的 WS web.config 中,我已经打开了所有缓冲区来发送和接收大数据:
web.config
<system.web>
<httpRuntime targetFramework="4.0" maxRequestLength ="2147483647" executionTimeout="999999"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" receiveTimeout="10:00:00" closeTimeout="10:00:00"
sendTimeout="10:00:00" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647" openTimeout="10:00:00" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://myDomain.pt/WStore/StoreService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService"
contract="StoreServices.IStoreService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
我的客户这样调用我的服务:
<?php
ini_set('default_socket_timeout', 360000);
class Car
{
public $Id=0;
public $Name="My new car";
public $Description="";
public $ImageBase64="";
}
$car_toInsert = new Car();
$requestParams = array('car' => $car_toInsert);
try {
$time_start = microtime(true);
$client = new SoapClient('http://myDomain.pt/WStore/StoreService.svc?wsdl',
array('encoding'=>'ISO-8859-1', 'keep_alive' => true,
'trace' => 1,
'exceptions'=> 1,
'connection_timeout'=> 3600));
$response = $client->SaveCarData($requestParams);
print_r($response);
} catch (Exception $e) {
$time_request = (microtime(true)-$time_start);
if(ini_get('default_socket_timeout') < $time_request) {
//Timeout error!
print_r("request time bigger");
} else {
//other error
//$error = $e->getMessage();
print_r($e->getMessage());
}
}
?>
我的客户已经像 here 中所说的那样打开了他的 "buffers"。
现在的问题是:当我的客户发送一个 "short" Car.ImageBase64
字符串时,这工作正常,但是当 Car.ImageBase64
字符串很大时,他可以与我的 WS 通信并获得此错误:请求实体太大
短 ImageBase64 示例:
class Car
{
public $Id=0;
public $Name="My new car";
public $Description="";
public $ImageBase64="data:image/jpg;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7";
}
巨大的 ImageBase64 示例:
我的 ImageBase64 字符串示例太大,无法插入此问题表单。请插入 url "http://d3eaqdewfg2crq.cloudfront.net/wp-content/uploads/carousel/main-reporting/report.png" in here 并编码为 base64.
问题是什么,我们该如何解决?我已经模拟了我的客户端通信来测试一些东西,我发现他正在发出一个 http GET 请求。我认为这可能是问题所在,我想将其更改为 http POST。我如何在 PHP 代码中执行此操作?
我也尝试像 this 那样更改我的网络配置,但我收到“SOAP-ERROR:解析 WSDL:找不到...”错误.
已解决!经过多次搜索和修改,我终于通过新的 web.config 更改解决了问题。我如何没有客户端端点,而是所有与我的 WS 通信的客户端的服务器端点。我还需要创建一个新服务(同一 WCF 项目中的 svc 和接口文件)并将我的 web.confi 更改为:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IStoreService"
receiveTimeout="10:00:00"
closeTimeout="10:00:00"
sendTimeout="10:00:00"
maxBufferPoolSize="2147483647"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
openTimeout="10:00:00"/>
<binding name="BasicHttpBinding_IServiceIntegration"
receiveTimeout="10:00:00"
closeTimeout="10:00:00"
sendTimeout="10:00:00"
maxBufferPoolSize="2147483647"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
openTimeout="10:00:00">
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="StoreServices.StoreService" behaviorConfiguration="StoreServicesBehavior"/>
<service name="StoreServices.IntegrationService" behaviorConfiguration="IntegrationServicesBehavior">
<endpoint address=""
binding="basicHttpBinding"
contract="StoreServices.IIntegrationService"
bindingConfiguration="BasicHttpBinding_IServiceIntegration" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="StoreServicesBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="IntegrationServicesBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<serviceActivations>
<add factory="System.ServiceModel.Activation.WebServiceHostFactory"
relativeAddress="./StoreServices/StoreService.svc"
service="StoreServices.StoreService" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
我有一个 soap svc 网络服务,这些是我的 WS 方法:
StoreService.svc.cs
namespace StoreServices
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class StoreService : IStoreService
{
public bool SaveCarData(Car car)
{
//Some code
}
}
}
IStoreService.cs
namespace StoreServices
{
[ServiceContract]
public interface IStoreService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/SaveCarData", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
bool SaveCarData(Car car);
}
}
在我的 WS web.config 中,我已经打开了所有缓冲区来发送和接收大数据:
web.config
<system.web>
<httpRuntime targetFramework="4.0" maxRequestLength ="2147483647" executionTimeout="999999"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService" receiveTimeout="10:00:00" closeTimeout="10:00:00"
sendTimeout="10:00:00" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647" openTimeout="10:00:00" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://myDomain.pt/WStore/StoreService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService"
contract="StoreServices.IStoreService"
name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
我的客户这样调用我的服务:
<?php
ini_set('default_socket_timeout', 360000);
class Car
{
public $Id=0;
public $Name="My new car";
public $Description="";
public $ImageBase64="";
}
$car_toInsert = new Car();
$requestParams = array('car' => $car_toInsert);
try {
$time_start = microtime(true);
$client = new SoapClient('http://myDomain.pt/WStore/StoreService.svc?wsdl',
array('encoding'=>'ISO-8859-1', 'keep_alive' => true,
'trace' => 1,
'exceptions'=> 1,
'connection_timeout'=> 3600));
$response = $client->SaveCarData($requestParams);
print_r($response);
} catch (Exception $e) {
$time_request = (microtime(true)-$time_start);
if(ini_get('default_socket_timeout') < $time_request) {
//Timeout error!
print_r("request time bigger");
} else {
//other error
//$error = $e->getMessage();
print_r($e->getMessage());
}
}
?>
我的客户已经像 here 中所说的那样打开了他的 "buffers"。
现在的问题是:当我的客户发送一个 "short" Car.ImageBase64
字符串时,这工作正常,但是当 Car.ImageBase64
字符串很大时,他可以与我的 WS 通信并获得此错误:请求实体太大
短 ImageBase64 示例:
class Car
{
public $Id=0;
public $Name="My new car";
public $Description="";
public $ImageBase64="data:image/jpg;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7";
}
巨大的 ImageBase64 示例:
我的 ImageBase64 字符串示例太大,无法插入此问题表单。请插入 url "http://d3eaqdewfg2crq.cloudfront.net/wp-content/uploads/carousel/main-reporting/report.png" in here 并编码为 base64.
问题是什么,我们该如何解决?我已经模拟了我的客户端通信来测试一些东西,我发现他正在发出一个 http GET 请求。我认为这可能是问题所在,我想将其更改为 http POST。我如何在 PHP 代码中执行此操作?
我也尝试像 this 那样更改我的网络配置,但我收到“SOAP-ERROR:解析 WSDL:找不到...”错误.
已解决!经过多次搜索和修改,我终于通过新的 web.config 更改解决了问题。我如何没有客户端端点,而是所有与我的 WS 通信的客户端的服务器端点。我还需要创建一个新服务(同一 WCF 项目中的 svc 和接口文件)并将我的 web.confi 更改为:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IStoreService"
receiveTimeout="10:00:00"
closeTimeout="10:00:00"
sendTimeout="10:00:00"
maxBufferPoolSize="2147483647"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
openTimeout="10:00:00"/>
<binding name="BasicHttpBinding_IServiceIntegration"
receiveTimeout="10:00:00"
closeTimeout="10:00:00"
sendTimeout="10:00:00"
maxBufferPoolSize="2147483647"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647"
openTimeout="10:00:00">
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="StoreServices.StoreService" behaviorConfiguration="StoreServicesBehavior"/>
<service name="StoreServices.IntegrationService" behaviorConfiguration="IntegrationServicesBehavior">
<endpoint address=""
binding="basicHttpBinding"
contract="StoreServices.IIntegrationService"
bindingConfiguration="BasicHttpBinding_IServiceIntegration" />
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="StoreServicesBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="IntegrationServicesBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<serviceActivations>
<add factory="System.ServiceModel.Activation.WebServiceHostFactory"
relativeAddress="./StoreServices/StoreService.svc"
service="StoreServices.StoreService" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>