2011-07-28 8 views
7

WCF 스트리밍 파일 전송에 대한 좋은 예가 필요합니다.WCF 스트리밍 파일 전송 .NET 4

몇 가지를 찾아서 사용해 보았지만 게시물이 오래되었고 .net 4와 IIS 7에서 문제가 있으므로 몇 가지 문제가 있습니다.

저에게 좋은 예를 들어 주시겠습니까?

+0

스트리밍이란 무엇을 의미합니까? 미디어 컨텐트 (I.E., 비디오 또는 MP3)에 WCF를 사용하려고합니까, 아니면 바이너리 정보를 다시 클라이언트로 보내는 것을 의미합니까? – Kane

+0

기본적으로 http를 통해 내 서버에 파일을 업로드하려고합니다. – tugberk

답변

7

다음은 게시 서비스 용 바이너리 데이터에 대해 몇 가지 기술을 사용하여 세부적인 답변을 제공합니다.

다음 코드는 당신이 편안하고 WCF 서비스를 쓸 수있는 방법의 샘플이며, 결코 완료하지만 당신에 대한 표시를 제공 않는다 너 시작 할 수있어.

샘플 서비스, 생산 준비 코드입니다.

[ServiceContract] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
public class FileService 
{ 
    private IncomingWebRequestContext m_Request; 
    private OutgoingWebResponseContext m_Response; 

    [WebGet(UriTemplate = "{appName}/{id}?action={action}")] 
    public Stream GetFile(string appName, string id, string action) 
    { 
     var repository = new FileRepository(); 
     var response = WebOperationContext.Current.OutgoingResponse; 
     var result = repository.GetById(int.Parse(id)); 

     if (action != null && action.Equals("download", StringComparison.InvariantCultureIgnoreCase)) 
     { 
      response.Headers.Add("Content-Disposition", string.Format("attachment; filename={0}", result.Name)); 
     } 

     response.Headers.Add(HttpResponseHeader.ContentType, result.ContentType); 
     response.Headers.Add("X-Filename", result.Name); 

     return result.Content; 
    } 

    [WebInvoke(UriTemplate = "{appName}", Method = "POST")] 
    public void Save(string appName, Stream fileContent) 
    { 
     try 
     { 
      if (WebOperationContext.Current == null) throw new InvalidOperationException("WebOperationContext is null."); 

      m_Request = WebOperationContext.Current.IncomingRequest; 
      m_Response = WebOperationContext.Current.OutgoingResponse; 

      var file = CreateFileResource(fileContent, appName); 

      if (!FileIsValid(file)) throw new WebFaultException(HttpStatusCode.BadRequest); 

      SaveFile(file); 

      SetStatusAsCreated(file); 
     } 
     catch (Exception ex) 
     { 
      if (ex.GetType() == typeof(WebFaultException)) throw; 
      if (ex.GetType().IsGenericType && ex.GetType().GetGenericTypeDefinition() == typeof(WebFaultException<>)) throw; 

      throw new WebFaultException<string>("An unexpected error occurred.", HttpStatusCode.InternalServerError); 
     } 
    } 

    private FileResource CreateFileResource(Stream fileContent, string appName) 
    { 
     var result = new FileResource(); 

     fileContent.CopyTo(result.Content); 
     result.ApplicationName = appName; 
     result.Name = m_Request.Headers["X-Filename"]; 
     result.Location = @"C:\SomeFolder\" + result.Name; 
     result.ContentType = m_Request.Headers[HttpRequestHeader.ContentType] ?? this.GetContentType(result.Name); 
     result.DateUploaded = DateTime.Now; 

     return result; 
    } 

    private string GetContentType(string filename) 
    { 
     // this should be replaced with some form of logic to determine the correct file content type (I.E., use registry, extension, xml file, etc.,) 
     return "application/octet-stream"; 
    } 

    private bool FileIsValid(FileResource file) 
    { 
     var validator = new FileResourceValidator(); 
     var clientHash = m_Request.Headers[HttpRequestHeader.ContentMd5]; 

     return validator.IsValid(file, clientHash); 
    } 

    private void SaveFile(FileResource file) 
    { 
     // This will persist the meta data about the file to a database (I.E., size, filename, file location, etc) 
     new FileRepository().AddFile(file); 
    } 

    private void SetStatusAsCreated(FileResource file) 
    { 
     var location = new Uri(m_Request.UriTemplateMatch.RequestUri.AbsoluteUri + "/" + file.Id); 
     m_Response.SetStatusAsCreated(location); 
    } 
} 

샘플 클라이언트는이 하지 생산 준비 코드 있습니다.

// ********************************* 
// Sample Client 
// ********************************* 
private void UploadButton_Click(object sender, EventArgs e) 
{ 
    var uri = "http://dev-fileservice/SampleApplication" 
    var fullFilename = @"C:\somefile.txt"; 
    var fileContent = File.ReadAllBytes(fullFilename); 

    using (var webClient = new WebClient()) 
    { 
     try 
     { 
      webClient.Proxy = null; 
      webClient.Headers.Add(HttpRequestHeader.ContentMd5, this.CalculateFileHash()); 
      webClient.Headers.Add("X-DaysToKeep", DurationNumericUpDown.Value.ToString()); 
      webClient.Headers.Add("X-Filename", Path.GetFileName(fullFilename)); 
      webClient.UploadData(uri, "POST", fileContent); 

      var fileUri = webClient.ResponseHeaders[HttpResponseHeader.Location]; 
      Console.WriteLine("File can be downloaded at" + fileUri); 
     } 
     catch (Exception ex) 
     { 
      var exception = ex.Message; 
     } 
    } 
} 

private string CalculateFileHash() 
{ 
    var hash = MD5.Create().ComputeHash(File.ReadAllBytes(@"C:\somefile.txt")); 
    var sb = new StringBuilder(); 

    for (int i = 0; i < hash.Length; i++) 
    { 
     sb.Append(hash[i].ToString("x2")); 
    } 

    return sb.ToString(); 
} 

private void DownloadFile() 
{ 
    var uri = "http://dev-fileservice/SampleApplication/1" // this is the URL returned by the Restful file service 

    using (var webClient = new WebClient()) 
    { 
     try 
     { 
      webClient.Proxy = null; 
      var fileContent = webClient.DownloadData(uri); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
    } 
} 
+0

괜찮습니까? 작은 파일은 좋지만 대용량 파일은 어떻습니까? REST 예제의 모든 코드 샘플은 훌륭합니다. – tugberk

+0

WCF 서비스 작성 방법에 대한 코드 샘플 – Kane

+0

위 예제입니다. 덕분에 곧 시도 할 수 있습니다. 당신은 편안한 방법이 SOAP 방식보다 낫다고 생각합니까? – tugberk