Служба WCF, размещенная на веб-сайте IIS, с TransferMode = Streamed throws w3wp.exe Исключение OutOfMemory? - PullRequest
0 голосов
/ 06 мая 2011

У меня есть служба WCF для загрузки и скачивания файлов.

Сервис: размещен на сайте IIS asp.net:

[ServiceContract]
public interface IFileTransferService
{
 [OperationContract(IsOneWay = true)]
 void Upload(FileTransferRequest request);
}

[MessageContract()]
public class FileTransferRequest
{
 [MessageHeader(MustUnderstand = true)]
 public string FileName;

 [MessageBodyMember(Order = 1)]
 public System.IO.Stream Data;

}

[AspNetCompatibilityRequirements(RequirementsMode= AspNetCompatibilityRequirementsMode.Required)]
public class FileTransferService : IFileTransferService
{
 public FileTransferService()
 {
  HttpContext httpContext = HttpContext.Current;

  if (httpContext != null)
  {
   httpContext.Response.BufferOutput = false;
  }
 }

 public void Upload(FileTransferRequest request)
 {
  string fileName = System.Guid.NewGuid().ToString() + request.FileName;

  if (ConfigurationManager.AppSettings["UploadPath"] == null)
  {
   throw new ApplicationException("Missing upload path");
  }

  string uploadPath = "/OutputFeeds";
  string filePath = Path.Combine(Path.GetFullPath(HttpContext.Current.Server.MapPath(uploadPath)), fileName);

  FileStream fs = null;
  try
  {
   fs = File.Create(filePath);
   byte[] buffer = new byte[1024];
   int read = 0;
   while ((read = request.Data.Read(buffer, 0, buffer.Length)) != 0)
   {
    fs.Write(buffer, 0, read);
   }
  }
  finally
  {
   if (fs != null)
   {
    fs.Close();
    fs.Dispose();
   }

   if (request.Data != null)
   {
    request.Data.Close();
    request.Data.Dispose();
   }
  }
 }    
}

Конфигурация сервера:

<system.serviceModel>
 <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
  </serviceHostingEnvironment>
 <bindings>
  <basicHttpBinding>
  <binding name="HttpBinding_MTOM" messageEncoding="Mtom" transferMode="Streamed" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
   <security mode="None">
   <transport clientCredentialType="None" />
   </security>
  </binding>

 </bindings>
 <services>

  <service behaviorConfiguration="FileTransferServiceBehavior"
  name="FileTransferService">
  <endpoint address="" binding="basicHttpBinding" bindingConfiguration="HttpBinding_MTOM"
   contract="IFileTransferService">
   <identity>
   <dns value="localhost" />
   </identity>
  </endpoint>
  <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

 </services>
 <behaviors>
  <serviceBehaviors>

  <behavior name="FileTransferServiceBehavior">
   <serviceMetadata httpGetEnabled="true" />
   <serviceDebug includeExceptionDetailInFaults="false" />
  </behavior>

  </serviceBehaviors>
 </behaviors>
 </system.serviceModel>

Клиент: вызов вышеуказанного сервиса из консольного приложения:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.serviceModel>
  <bindings>
   <basicHttpBinding>
    <binding name="BasicHttpBinding_IFileTransferService" closeTimeout="00:01:00"
     openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
     allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
     maxBufferSize="65536" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
     messageEncoding="Mtom" textEncoding="utf-8" transferMode="Streamed"
     useDefaultWebProxy="true">
     <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
      maxBytesPerRead="4096" maxNameTableCharCount="16384" />
     <security mode="None">
      <transport clientCredentialType="None" proxyCredentialType="None"
       realm="">
       <extendedProtectionPolicy policyEnforcement="Never" />
      </transport>
      <message clientCredentialType="UserName" algorithmSuite="Default" />
     </security>
    </binding>

   </basicHttpBinding>
  </bindings>
  <client>
   <endpoint address="http://ht/FileTransferService.svc" binding="basicHttpBinding"
    bindingConfiguration="BasicHttpBinding_IFileTransferService"
    contract="HobbyTown.IFileTransferService" name="BasicHttpBinding_IFileTransferService" />

  </client>
 </system.serviceModel>
</configuration>

Код загрузки клиента:

 string inputFile = @"C:\Client\InputFeeds\FullInventory.zip";
 using (FileStream fs = new FileStream(inputFile, FileMode.Open))
 {
    FileTransferServiceClient proxy = new FileTransferServiceClient();
    proxy.Upload("Inventory.Zip", fs);
    //proxy.Upload(trIn);
 }

Примечание: если я изменяю режим передачи на буферизованный в клиенте, он работает, а если «Сделать режим передачи на клиенте» на «Потоковый», он не работает и выдает ошибку памяти.

Еще один пост для той же проблемы

1 Ответ

0 голосов
/ 07 мая 2011

Мне хотелось бы знать, не заставляет ли поток вести себя как буферизованный на стороне службы. Что такое FileTransferRequest - это сторонний? Потоковая передача в WCF обычно требует, чтобы поток был единственным параметром в вашем доступном методе обслуживания.

http://msdn.microsoft.com/en-us/library/ms733742.aspx

"Обратите внимание, что добавление второго параметра в следующие операции Echo или ProvideInfo заставляет сервисную модель вернуться к буферизованной стратегии и использовать представление сериализации во время выполнения потока. Совместимы только операции с одним параметром входного потока с сквозной потоковой передачей запросов.

Это правило аналогично применяется к контрактам на сообщения. Как показано в следующем контракте сообщений, в контракте сообщений может быть только один элемент тела, который является потоком. Если вы хотите передать дополнительную информацию потоку, эта информация должна быть перенесена в заголовки сообщения. Тело сообщения зарезервировано исключительно для содержимого потока. "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...