WCF流式PDF响应



我的目标是将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>

现在在客户端(例如控制台应用程序),当我创建服务引用时,我希望看到我的基本HttpBinding 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没有匹配绑定的内容类型(text/xml;charset=utf-8)。

如何强制客户端接受WCF端定义的流式配置?

感谢

这是一个经过测试的控制台应用程序。只需在可执行文件中创建"Files"目录,将文件放入其中,然后将类似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:如果你愿意,如果没有修改代码,你可以删除,只是如果客户端有最新的版本,就不要重新发送同一个文件。

最新更新