2016-04-09 43 views
0

我的目標是將PDF文件流返回給客戶端。WCF流式PDF響應

所以在WCF身邊,我有:

public interface IPersonalPropertyService 
    { 
     [OperationContract] 
     Stream GetQuotation(); 
    } 

public class PersonalPropertyService : IPersonalPropertyService 
    { 
     public Stream GetQuotation() 
     { 
      var filePath = HostingEnvironment.ApplicationPhysicalPath + @"Quotation.pdf"; 
      var fileInfo = new FileInfo(filePath); 
      // check if exists 
      if (!fileInfo.Exists) 
       throw new FileNotFoundException("File not found"); 
      FileStream stm = File.Open(filePath, FileMode.Open); 
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/pdf"; 
      return stm; 
     } 
    } 

配置部分如下:

<system.serviceModel> 
    <client> 
     <endpoint 
     binding="basicHttpBinding" 
     bindingConfiguration="StreamedHttp" 
     contract="IPersonalPropertyService" > 
     </endpoint> 
    </client> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="StreamedHttp" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" 
      transferMode="Streamed"> 
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" 
      maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 

    <behaviors> 
     <serviceBehaviors> 
     <behavior> 
      <!-- To avoid disclosing metadata information, set the values below to false before deployment --> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
      <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> 
      <serviceDebug includeExceptionDetailInFaults="false"/> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 

現在在客戶端(如控制檯應用程序),當我創建服務引用,我期望看到我的basicHttpBinding StreamedHttp配置,但生成以下配置:

<system.serviceModel> 
     <bindings> 
      <basicHttpBinding> 
       <binding name="BasicHttpBinding_PersonalPropertyService" /> 
      </basicHttpBinding> 
     </bindings> 
     <client> 
      <endpoint address="MyPath/PersonalPropertyService.svc" 
       binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_PersonalPropertyService" 
       contract="TheNamespace.ServiceReference.PersonalPropertyService" 
       name="BasicHttpBinding_PersonalPropertyService" /> 
     </client> 
    </system.serviceModel> 

,我估計是因爲這個原因,我得到一個異常的ProtocolException說

響應消息的內容類型application/PDF格式不匹配 內容類型的綁定(文本/ XML的;字符集= UTF-8)。

如何強制客戶端接受WCF端定義的流式配置?

謝謝

+0

當你在瀏覽器中輸入「http://....../ GetQuotation」時,你會得到什麼? – Eser

+0

我改變了web.config與瀏覽器進行交互,現在當我執行http://..../PersonalPropertyService.svc/GetQuotation時,我得到:方法不允許。 – Nostradamus

+0

我從來沒有能夠讀取WCF conf文件,但如果您有興趣,我可以發佈一個基於WebServiceHost的自託管WCF服務器,返回文件 – Eser

回答

3

這是一個經過測試的控制檯應用程序。只需在您的可執行文件中創建「文件」目錄,將您的文件放入其中,然後將類似http://localhost:8088/fileServer/a.pdf的東西粘貼到您的瀏覽器中。

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Web; 
using System.Text; 
using System.Web; 

namespace SampleWCFConsoleApplication 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      FileServer.Start(); 
     } 
    } 

    [ServiceContract] 
    public class FileServer 
    { 
     static WebServiceHost _Host; 
     public static void Start() 
     { 
      _Host = new WebServiceHost(typeof(FileServer), new Uri("http://0.0.0.0:8088/FileServer")); 
      _Host.Open(); 
      Console.ReadLine(); 
     } 

     [OperationContract, WebGet(UriTemplate = "*")] 
     public Message Get() 
     { 
      var ctx = WebOperationContext.Current; 

      var fileName = Path.Combine("Files", String.Join("/", WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RelativePathSegments)); 

      var fInfo = new FileInfo(fileName); 

      var eTag = ctx.IncomingRequest.Headers[HttpRequestHeader.IfNoneMatch]; 
      if (!string.IsNullOrEmpty(eTag)) 
      { 
       if (GetETag(fInfo) == eTag) 
       { 
        ctx.OutgoingResponse.StatusCode = HttpStatusCode.NotModified; 
        return ctx.CreateTextResponse(""); 
       } 
      } 

      if (fInfo.Exists == false) return ReturnError(ctx, HttpStatusCode.NotFound); 
      return ReturnFile(ctx, fInfo); 
     } 

     static string GetETag(FileInfo fInfo) 
     { 
      return Convert.ToBase64String(Encoding.UTF8.GetBytes(fInfo.Name).Concat(BitConverter.GetBytes(fInfo.LastWriteTime.Ticks)).ToArray()); 
     } 

     public static Message ReturnError(WebOperationContext ctx, HttpStatusCode statusCode) 
     { 
      ctx.OutgoingResponse.StatusCode = statusCode; 
      return ctx.CreateTextResponse(statusCode.ToString(), "text/html"); 
     } 

     static Message ReturnFile(WebOperationContext ctx, FileInfo fInfo, HttpStatusCode statusCode = HttpStatusCode.OK) 
     { 
      ctx.OutgoingResponse.StatusCode = statusCode; 
      ctx.OutgoingResponse.ETag = GetETag(fInfo); 

      return ctx.CreateStreamResponse(File.OpenRead(fInfo.FullName), MimeMapping.GetMimeMapping(fInfo.Name)); 
     } 
    } 
} 

BTW:如果你願意,你可以刪除如果 - 不修改代碼,它是不重新發送相同的文件,如果客戶有UPTODATE版本。

+1

非常感謝你@ – Nostradamus