2010-08-31 149 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字節,但它沒有任何東西可以發送,但...