Потоковая служба wcf возвращает поврежденный поточный файл - PullRequest
1 голос
/ 31 августа 2010

У меня есть служба WCF, которая возвращает объект потока.Но по какой-то причине я получаю поврежденный zip-файл, который я передаю в потоковом режиме.Весь код указан ниже. Пожалуйста, сообщите

Код договора

[ServiceContract(Namespace = "http://schemas.acme.it/2009/04/01")]
public interface IFileTransferService
{
    [OperationContract(IsOneWay = false)]
    FileDownloadReturnMessage DownloadFile(FileDownloadMessage request);

    [OperationContract()]
    string HellowWorld(string name);

}

[MessageContract]
public class FileDownloadMessage
{
    [MessageHeader(MustUnderstand = true)]
    public FileMetaData FileMetaData;
}

[MessageContract]
public class FileDownloadReturnMessage
{
    public FileDownloadReturnMessage(FileMetaData metaData, Stream stream)
    {
        this.DownloadedFileMetadata = metaData;
        this.FileByteStream = stream;
    }

    [MessageHeader(MustUnderstand = true)]
    public FileMetaData DownloadedFileMetadata;
    [MessageBodyMember(Order = 1)]
    public Stream FileByteStream;
}


[DataContract(Namespace = "http://schemas.acme.it/2009/04/01")]
public class FileMetaData
{
    public FileMetaData(string [] productIDs, string authenticationKey)
    {
        this.ids = productIDs;
     this.authenticationKey= authenticationKey;
    }

    [DataMember(Name = "ProductIDsArray", Order = 1, IsRequired = true)]
    public string[] ids;
    [DataMember(Name = "AuthenticationKey", Order = 2, IsRequired = true)]
    public string authenticationKey;
}

Код файла SVC

public class DownloadCoverScan : IFileTransferService
{
    public FileDownloadReturnMessage DownloadFile(FileDownloadMessage request)
    {
        FileStream stream = new FileStream(@"C:\Pictures.zip", FileMode.Open,
                                           FileAccess.Read);
        FileMetaData metaData= new FileMetaData(new string[] { "1", "2" },"asd");
        FileDownloadReturnMessage returnMessage =
            new FileDownloadReturnMessage(metaData,stream);
        return returnMessage;
    }
    public string HellowWorld(string name)
    {
        return "Hello " + name;
    }

}

Код конфигурации

<system.serviceModel>
<behaviors>
  <serviceBehaviors>
    <behavior name="DownloadCoverScanBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true" />
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service behaviorConfiguration="DownloadCoverScanBehavior" name="DownloadService.DownloadCoverScan">
    <endpoint address="" name="basicHttpStream" binding="basicHttpBinding" bindingConfiguration="httpLargeMessageStream"
              contract="DownloadService.IFileTransferService" />
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="httpLargeMessageStream" maxReceivedMessageSize="2147483647" transferMode="Streamed"  messageEncoding="Mtom" />
  </basicHttpBinding>
</bindings>
</system.serviceModel>

Код клиента

FileMetaData metaData = new FileMetaData();
metaData.ProductIDsArray = new string[] { "1", "2" };
metaData.AuthenticationKey = "test";
FileDownloadMessage inputParam = new FileDownloadMessage(metaData);
FileTransferServiceClient obj = new FileTransferServiceClient();
FileDownloadReturnMessage outputMessage = obj.DownloadFile(inputParam);
Byte[] buffer = new Byte[8192];
int byteRead = outputMessage.FileByteStream.Read(buffer, 0, buffer.Length);
Response.Buffer = false;
Response.ContentType = "application/zip";
Response.AppendHeader("content-length", buffer.Length.ToString());
Response.AddHeader("Content-disposition", "attachment; filename=testFile.zip");
Stream outStream = Response.OutputStream;
while (byteRead > 0)
{
    outStream.Write(buffer, 0, byteRead);
    byteRead = outputMessage.FileByteStream.Read(buffer, 0, buffer.Length);
}
outputMessage.FileByteStream.Close();
outStream.Close();

Ответы [ 2 ]

1 голос
/ 31 августа 2010

Я думаю, что проблема может быть в заголовке Content-Length из ответа. Вы устанавливаете его на 8192, в то время как вы еще не знаете длину.

Я не совсем уверен, однако. Может быть, это пойдет не так в начале процесса. Может быть, вы можете поместить в свой клиентский код какой-нибудь протокол записи, чтобы убедиться, что вы действительно записываете все байты в выходной поток (например, регистрируя byteRead).

0 голосов
/ 23 ноября 2010

Это может быть связано с тем, как вы закрываете свой поток на стороне сервера. У меня был проект, похожий на этот, где клиент передавал поток в асинхронном вызове на сервер, и иногда файл .zip повреждался. Оказалось, что я не закрывал поток на стороне клиента должным образом, что привело к неполному потоку.

Я не видел код, который показывал, что служба закрывает поток, отправленный на стороне службы.

Я считаю, что поток не будет завершен должным образом, если он не будет закрыт. Вы все еще можете прочитать 0 байтов, когда ему больше нечего отправить ...

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