开发者

Streaming wcf service returning corrupt streamed file

开发者 https://www.devze.com 2023-01-14 00:26 出处:网络
I have a WCF service that returns a stream object. But for some reason i get a corrupt zip file back which i am streaming. All the code is below Please advise

I have a WCF service that returns a stream object. But for some reason i get a corrupt zip file back which i am streaming. All the code is below Please advise

Contract Code

[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 file code

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;
    }

}

Config code

<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>

Client Code

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();


I think the problem may be the Content-Length header from the response. You set it to 8192 while you actually don't know the length yet.

I'm not absolutely sure, however. Maybe it goes wrong earlier in the process. Maybe you can put some logging statement in your client code to be sure that you actually write all bytes to the output stream (by logging byteRead for example).


This could have to do with how you close your stream on the Server side. I had a project similar to this where the client was passing a stream in an Async call to the server, and the .zip file was corrupted sometimes. It turned out that I wasn't closing the stream on the client side properly resulting in an incomplete stream.

I didn't see code that showed the service closing the stream it sent on the service side.

I believe a stream won't complete properly unless it's closed. You can still read 0 bytes when it has nothing left to send though...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号