无法使用 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);
            }
        }