无法使用 WCF 上传图片
Unable to upload image using WCF
我正在开发一个示例 Xamarin.Forms 应用程序,该应用程序会拍照,然后将其上传到远程服务器。上传部分由部署在远程 IIS 上的 WCF 服务处理。
客户端部分没问题,但是当流量到达服务器部分时,我收到这个错误:
System.Net.WebException: There was an error in processing web request: Status code 413(RequestEntityTooLarge): Request Entity Too Large
我试图在 WCF web.config 和部署服务的站点中增加消息的最大大小。
低于服务的web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="GlobalEndpoint">
<dataContractSerializer maxItemsInObjectGraph="1365536" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="GlobalBehavior">
<dataContractSerializer maxItemsInObjectGraph="1365536" />
</behavior>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding
name="BasicHttpBinding_IQuery_service"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
transferMode="Streamed">
<readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://path/to/service.svc"
binding="webHttpBinding" bindingConfiguration="BasicHttpBinding_IQuery_service"
contract="IQuery_service" name="BasicHttpBinding_IQuery_service" />
</client>
<protocolMapping>
<add binding="webHttpBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
在站点配置编辑器的设置下方,WCF服务部署位置:
下面我调用的上传图片的方法:
public bool UploadToFolder(byte[] file_bytes, string file_name)
{
bool isSuccess = false;
FileStream fileStream = null;
//Get the file upload path store in web services web.config file.
string strFolderPath = System.Configuration.ConfigurationManager.AppSettings.Get(@"dest\path");
try
{
if (!string.IsNullOrEmpty(strFolderPath))
{
if (!string.IsNullOrEmpty(file_name))
{
string strFileFullPath = strFolderPath + file_name;
fileStream = new FileStream(strFileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
// write file stream into the specified file
using (System.IO.FileStream fs = fileStream)
{
fs.Write(file_bytes, 0, file_bytes.Length);
isSuccess = true;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return isSuccess;
}
我不知道这是否是从 Xamarin 应用程序执行上传到远程服务器的最佳方式,欢迎任何建议。
编辑
已经尝试在 web.config 中递增 maxReceivedMessageSize
,但没有成功。
比如我在服务的主页上看到,我运行命令svcutil.exe http://server_address/path/to/service.svc?wdsl
,然后我添加了file.cs 到我的解决方案,并从中调用 varius 方法。
调用上传方法的代码:
try
{
Query_serviceClient client = new Query_serviceClient(http_binding, endpoint_address);
client.UploadToTempFolder(filebyte, filename);
client.Close();
}
catch (Exception ex)
{
DisplayAlert("ERROR", ex.ToString(), "OK");
}
在回答问题之前,我们应该弄清楚你调用WCF服务的方式。这决定了您要调用服务的方式,然后将配置应用到正确的服务(Soap Web 服务或 Rest 样式)。
根据上面的服务配置,在IIS中托管服务是无效的,即WCF服务运行不当,更何况调用时出错。如果我们尝试访问服务 WSDL
,我们将看到错误详细信息。
您是使用客户端代理上传图片,还是直接实例化一个 HttpClient
class 来创建一个 post 到服务端点地址的请求?
如果选择第一种方式上传图片,请参考以下配置。
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding
name="mybinding"
maxReceivedMessageSize="2147483647">
</binding>
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" bindingConfiguration="mybinding"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
如果你想创建一个Restful风格的WCF服务,即第二种选择,请参考下面的配置。
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="rest" maxReceivedMessageSize="2147483647">
</binding>
</webHttpBinding>
</bindings>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" bindingConfiguration="rest"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
如果问题仍然存在,请随时告诉我。
解决办法是改变上传的方法。
最后上传图片我使用了这个简单干净的解决方案:
public void UploadFile(Stream file_stream)
{
using (var output = File.Open("dest/for/image.jpg", FileMode.Create, FileAccess.ReadWrite))
{
file_stream.CopyTo(output);
}
}
我正在开发一个示例 Xamarin.Forms 应用程序,该应用程序会拍照,然后将其上传到远程服务器。上传部分由部署在远程 IIS 上的 WCF 服务处理。
客户端部分没问题,但是当流量到达服务器部分时,我收到这个错误:
System.Net.WebException: There was an error in processing web request: Status code 413(RequestEntityTooLarge): Request Entity Too Large
我试图在 WCF web.config 和部署服务的站点中增加消息的最大大小。
低于服务的web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
</system.web>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="GlobalEndpoint">
<dataContractSerializer maxItemsInObjectGraph="1365536" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="GlobalBehavior">
<dataContractSerializer maxItemsInObjectGraph="1365536" />
</behavior>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding
name="BasicHttpBinding_IQuery_service"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647"
transferMode="Streamed">
<readerQuotas maxDepth="2000000" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://path/to/service.svc"
binding="webHttpBinding" bindingConfiguration="BasicHttpBinding_IQuery_service"
contract="IQuery_service" name="BasicHttpBinding_IQuery_service" />
</client>
<protocolMapping>
<add binding="webHttpBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
在站点配置编辑器的设置下方,WCF服务部署位置:
下面我调用的上传图片的方法:
public bool UploadToFolder(byte[] file_bytes, string file_name)
{
bool isSuccess = false;
FileStream fileStream = null;
//Get the file upload path store in web services web.config file.
string strFolderPath = System.Configuration.ConfigurationManager.AppSettings.Get(@"dest\path");
try
{
if (!string.IsNullOrEmpty(strFolderPath))
{
if (!string.IsNullOrEmpty(file_name))
{
string strFileFullPath = strFolderPath + file_name;
fileStream = new FileStream(strFileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
// write file stream into the specified file
using (System.IO.FileStream fs = fileStream)
{
fs.Write(file_bytes, 0, file_bytes.Length);
isSuccess = true;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
return isSuccess;
}
我不知道这是否是从 Xamarin 应用程序执行上传到远程服务器的最佳方式,欢迎任何建议。
编辑
已经尝试在 web.config 中递增 maxReceivedMessageSize
,但没有成功。
比如我在服务的主页上看到,我运行命令svcutil.exe http://server_address/path/to/service.svc?wdsl
,然后我添加了file.cs 到我的解决方案,并从中调用 varius 方法。
调用上传方法的代码:
try
{
Query_serviceClient client = new Query_serviceClient(http_binding, endpoint_address);
client.UploadToTempFolder(filebyte, filename);
client.Close();
}
catch (Exception ex)
{
DisplayAlert("ERROR", ex.ToString(), "OK");
}
在回答问题之前,我们应该弄清楚你调用WCF服务的方式。这决定了您要调用服务的方式,然后将配置应用到正确的服务(Soap Web 服务或 Rest 样式)。
根据上面的服务配置,在IIS中托管服务是无效的,即WCF服务运行不当,更何况调用时出错。如果我们尝试访问服务 WSDL
,我们将看到错误详细信息。
您是使用客户端代理上传图片,还是直接实例化一个 HttpClient
class 来创建一个 post 到服务端点地址的请求?
如果选择第一种方式上传图片,请参考以下配置。
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding
name="mybinding"
maxReceivedMessageSize="2147483647">
</binding>
</basicHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpBinding" scheme="http" bindingConfiguration="mybinding"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
如果你想创建一个Restful风格的WCF服务,即第二种选择,请参考下面的配置。
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="rest" maxReceivedMessageSize="2147483647">
</binding>
</webHttpBinding>
</bindings>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" bindingConfiguration="rest"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
如果问题仍然存在,请随时告诉我。
解决办法是改变上传的方法。
最后上传图片我使用了这个简单干净的解决方案:
public void UploadFile(Stream file_stream)
{
using (var output = File.Open("dest/for/image.jpg", FileMode.Create, FileAccess.ReadWrite))
{
file_stream.CopyTo(output);
}
}