2010-08-31 46 views
1

我有一个WCF服务,返回一个流对象。但由于某种原因,我收到了一个损坏的zip文件,我正在流式传输。所有的代码是下面请大家指教流wcf服务返回损坏的流文件

合约代码

[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(); 
+0

下载的文件是否与原始文件大小完全相同? – 2010-08-31 07:51:41

+0

嗯,我无法打开下载的文件,所以不能确定它是否完全一样 – Amit 2010-08-31 07:54:41

+0

为什么你两次发表相同的问题? – 2010-08-31 07:55:14

回答

1

我认为该问题可能是从响应中Content-Length报头。你将它设置为8192,而你实际上还不知道长度。

但我并不十分确定。在这个过程中可能会出现错误。也许你可以在你的客户端代码中加入一些日志语句,以确保你实际上将所有字节写入输出流(例如通过记录byteRead)。

+0

好吧,感谢您的答复 – Amit 2010-08-31 08:48:07

+0

罗纳德,我改变了下面的行,增加了字节数组的大小,使它可以容纳278kb文件,并开始工作。但我仍然不确定如果一个文件是abt,我指定的大小为300 MB Byte [] buffer = new Byte [355841112]; – Amit 2010-08-31 08:51:40

+0

我不认为问题是缓冲区大小,并且从流中读取的代码不包含任何错误,据我所见。我认为你应该试着找出为什么8KB的缓冲区大小通过向你的代码添加一些日志记录而不起作用。大缓冲区大小的问题在于您将整个流加载到内存中,而这正是您使用流时要防止的情况。 – 2010-08-31 11:19:57

0

这可能与您如何关闭服务器端的流有关。我有一个类似于这样的项目,其中客户端将Async调用中的流传递给服务器,并且.zip文件有时会被损坏。事实证明,我没有正确关闭客户端的流,导致流不完整。

我没有看到代码显示服务关闭了它在服务端发送的流。

我相信一个流不会正确地完成,除非它被关闭。你仍然可以读取0字节,但它没有任何东西可以发送,但...