tags:

views:

26

answers:

1

Hi Guys, 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();
+2  A: 

The buffer size doesn't matter much, just pick a reasonable size, like:

Byte[] buffer = new Byte[8192];

There is also an error in your code, where you write the contents of the buffer:

outStream.Write(buffer, 0, buffer.Length);

should be:

outStream.Write(buffer, 0, byteRead);

Otherwise you will always write the entire buffer even if it's only partially filled with data.

Guffa
Thanks for the reply, I have made the changes as advised, and i can see that i am able to download my zip file, but when i extract it then i get an error. So not sure where the error is is it int he WCF service or the client. I have updated my question with all the code. Please advise
Amit
@Amit: The problem is that you are setting the content-length to the buffer size. If you can find out the actual stream size you can use that, otherwise you have to skip the content-length attribute.
Guffa
@guffa-- alright i will make the change. thanks
Amit