【问题标题】:How to upload a file to a .NET 3.5 WCF service hosted in IIS?如何将文件上传到 IIS 中托管的 .NET 3.5 WCF 服务?
【发布时间】:2011-10-20 10:48:35
【问题描述】:

我已经扯掉头发有一段时间了。有人可以提供一个非常简单的示例(或工作示例的链接),说明如何将文件上传到 IIS 中托管的 WCF 服务。

我从一些简单的事情开始。我想通过 POST 从客户端调用 URL,传递文件名并发送文件。所以我在合同中添加了以下内容:

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/UploadFile?fileName={fileName}")]
void Upload(string fileName, Stream stream);

在 .svc 文件中实现它:

public void Upload(string fileName, Stream stream)
{
    Debug.WriteLine((fileName));
}

立即,我在运行项目时遇到错误:

For request in operation Upload to be a stream the operation must have a single parameter whose type is Stream.

不知道从这里去哪里。希望看到一个实际的工作示例。

附:我在 .NET 4 中使用 WCF 4 进行了此操作,它看起来要简单得多,但我不得不降级。在 .NET 3.5 中,我遗漏了一些东西。

【问题讨论】:

    标签: c# wcf iis .net-3.5 file-upload


    【解决方案1】:

    为了使其工作,您需要定义一个端点,其绑定与WebHttpBinding 兼容,并添加了WebHttpBehavior。该消息可能是一条红鲱鱼,它是一个旧错误,如果您浏览到服务基址,并且如果您启用了元数据,它将显示出来。另一个问题是,如果您希望能够上传 任何 文件类型(包括 JSON 和 XML),您需要定义一个 WebContentTypeMapper 来告诉 WCF 不要尝试理解您的文件(更多信息http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx)。

    这是一个完整的例子。 3.5 的最大问题是 WebHttpBinding 上不存在 ContentTypeMapper 属性,因此您需要为此使用自定义绑定。此代码使用自定义 ServiceHostFactory 定义端点,但也可以使用 config 定义。

    Service.svc

    <%@ ServiceHost Language="C#" Debug="true" Service="MyNamespace.MyService" Factory="MyNamespace.MyFactory" %>
    

    Service.cs

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Web;
    
    public class MyNamespace
    {
        [ServiceContract]
        public interface IUploader
        {
            [OperationContract]
            [WebInvoke(Method = "POST", UriTemplate = "/UploadFile?fileName={fileName}")]
            void Upload(string fileName, Stream stream);
        }
    
        public class Service : IUploader
        {
            public void Upload(string fileName, Stream stream)
            {
                Debug.WriteLine(fileName);
            }
        }
    
        public class MyFactory : ServiceHostFactory
        {
            protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
            {
                return new MyServiceHost(serviceType, baseAddresses);
            }
    
            class MyRawMapper : WebContentTypeMapper
            {
                public override WebContentFormat GetMessageFormatForContentType(string contentType)
                {
                    return WebContentFormat.Raw;
                }
            }
    
            public class MyServiceHost : ServiceHost
            {
                public MyServiceHost(Type serviceType, Uri[] baseAddresses)
                    : base(serviceType, baseAddresses) { }
    
                protected override void OnOpening()
                {
                    base.OnOpening();
    
                    CustomBinding binding = new CustomBinding(new WebHttpBinding());
                    binding.Elements.Find<WebMessageEncodingBindingElement>().ContentTypeMapper = new MyRawMapper();
                    ServiceEndpoint endpoint = this.AddServiceEndpoint(typeof(IUploader), binding, "");
                    endpoint.Behaviors.Add(new WebHttpBehavior());
                }
            }
        }
    }
    

    【讨论】:

    • 我复制了您的解决方案,但出现此错误:A binding instance has already been associated to listen URI 'http://localhost:51147/FileUploader.svc'. If two endpoints want to share the same ListenUri, they must also share the same binding object instance. The two conflicting endpoints were either specified in AddServiceEndpoint() calls, in a config file, or a combination of AddServiceEndpoint() and config.
    • 您在 web.config 上是否有任何向该地址添加端点的内容?你能发布你的web.config吗?使用此解决方案,您的服务实际上完全不需要 web.config
    • 你是对的。我删除了 web.config,让 IDE 为我生成一个新的,然后页面出现了,我可以上传文件。我必须在 WebHttpBinding 对象上指定 MaxReceivedMessageSize 才能获得大于默认值的文件。
    • 我剩下的问题是如何确定我在文件系统中的位置?由于HttpContext.Current为空,所以不能用HttpContext.Current.Server.MapPath来确定文件夹,这样就可以保存上传的文件了。
    • 您可以使用System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath在服务器中查找路径。
    猜你喜欢
    • 2011-10-04
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 2011-03-23
    相关资源
    最近更新 更多