如何将文件上传到IIS中托管的.net 3.5 WCF服务
本文关键字:net 服务 WCF 文件 IIS | 更新日期: 2023-09-27 18:04:38
我已经抓狂一阵子了。有人能提供一个非常简单的例子(或一个链接到一个工作的例子)如何上传一个文件到托管在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中,我缺少了一些东西。
为了使其工作,您需要定义一个与WebHttpBinding
兼容的绑定端点,并将WebHttpBehavior
添加到其中。这条消息可能是转移注意力,这是一个老bug,如果你浏览到服务基地地址,如果你启用了元数据,它就会显示出来。另一个问题是,如果你想能够上传任何文件类型(包括JSON和XML),你需要定义一个WebContentTypeMapper来告诉WCF不要试图理解你的文件(更多信息见http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx)。
这是一个完整的例子。3.5最大的问题是ContentTypeMapper属性在WebHttpBinding上不存在,所以你需要使用自定义绑定。这段代码使用自定义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());
}
}
}
}