2011-08-04 4 views
2

나는 잠시 동안 머리카락을 찢어 내고 있었다. 누군가 IIS에서 호스팅되는 WCF 서비스에 파일을 업로드하는 방법에 대한 간단한 예제 (또는 실제 예제에 대한 링크)를 제공 할 수 있습니까?IIS에서 호스팅되는 .NET 3.5 WCF 서비스에 파일을 업로드하는 방법은 무엇입니까?

나는 간단한 것을 시작했다. POST를 통해 클라이언트의 URL을 호출하고 파일의 이름을 전달하고 파일을 보내려고합니다.

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

은 SVC는 파일에 구현 : 그래서 나는이 계약에 다음과 같은 추가

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

: 즉시

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

을, 나는 프로젝트를 실행에 오류가

여기에서 어디로 가는지 잘 모르겠습니다. 실제 작업 예제를보고 싶습니다.

P. .NET 4에서 WCF 4로이 작업을 수행했는데 훨씬 단순 해 보였지만 다운 그레이드해야했습니다. .NET 3.5에서는 뭔가 빠졌습니다.

답변

4

작동하려면 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의 가장 큰 문제점은 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()); 
      } 
     } 
    } 
} 
+0

나는 솔루션을 복사,하지만 난이 오류를 얻고있다 :'바인딩 인스턴스가 이미 URI를 듣고 관련되어있다 'http : // localhost : 51147/FileUploader.svc'. 두 개의 엔드 포인트가 동일한 ListenUri을 공유하려는 경우에도 동일한 바인딩 오브젝트 인스턴스를 공유해야합니다. 충돌하는 두 종점은 AddServiceEndpoint() 호출, 설정 파일 또는 AddServiceEndpoint()와 config의 조합으로 지정되었습니다. – AngryHacker

+0

web.config에서 해당 주소에 끝점을 추가하는 항목이 있습니까? web.config를 게시 할 수 있습니까? 이 솔루션을 사용하면 실제로 귀하의 서비스에 대해 web.config *가 필요하지 않습니다. – carlosfigueira

+0

당신 말이 맞아요. web.config를 삭제하고 IDE에서 새 파일을 생성하고 페이지가 나타나서 파일을 업로드 할 수 있습니다. 나는 WebHttpBinding 객체에'MaxReceivedMessageSize'를 지정하여 파일을 기본값보다 크게 얻을 수있게해야했습니다. – AngryHacker

관련 문제