tags:

views:

31

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();
+1  A: 

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

Ronald Wildenberg
alright, thanks for the reply
Amit
Ronald, I changed the below line and increased the size of byte array so that it can accommodate 278kb file and it started working. but i am still unsure wht size do i specify if a file is abt 300 mb Byte[] buffer = new Byte[355841112];
Amit
I don't think the problem was the buffer size and the code for reading from the stream doesn't contain any errors as far as I can see. I think you should try to find out why a buffer size of 8KB isn't working by adding some logging to your code. The problem with large buffer sizes is that you load the entire stream into memory and that's exactly what you want to prevent when using streams.
Ronald Wildenberg