WCF传送二进制流数据基本实现步骤详解

我们知道,在实现WCF传送二进制流数据这一操作过程中,会有一些限制因素。我们在实际应用中要特别注意这一点。今天我们就会针对这方面的问题做一个详细的介绍,希望对大家有所帮助。#t#

创新互联是一家专注于成都网站制作、网站建设与策划设计,卢龙网站建设哪家好?创新互联做网站,专注于网站建设十载,网设计领域的专业建站公司;建站业务涵盖:卢龙等地区。卢龙做网站价格咨询:18980820575

只有 BasicHttpBinding、WebHttpBinding、NetTcpBinding 和 NetNamedPipeBinding 支持传送流数据。
流数据类型必须是可序列化的 Stream 或 MemoryStream。
传递时消息体(Message Body)中不能包含其他数据。

我们先看看下面的WCF传送二进制流数据例子。

注意将 Binding.TransferMode 设置为 TransferMode.Streamed,我们还可以修改 Binding.MaxReceivedMessageSize 来调整消息大小(默认是64KB)。

 
 
 
  1. [ServiceContract]  
  2. public interface IFileService  
  3. {  
  4. [OperationContract]  
  5. void Upload(Stream stream);  
  6. }  
  7. public class FileService : IFileService, IDisposable  
  8. {  
  9. public void Upload(Stream stream)  
  10. {  
  11. FileStream file = new FileStream("test.dll", FileMode.Create);  
  12. try  
  13. {  
  14. BinaryWriter writer = new BinaryWriter(file);  
  15. BinaryReader reader = new BinaryReader(stream);  
  16. byte[] buffer;  
  17. do  
  18. {  
  19. buffer = reader.ReadBytes(1024);  
  20. writer.Write(buffer);  
  21. }  
  22. while (buffer.Length > 0);  
  23. }  
  24. finally  
  25. {  
  26. file.Close();  
  27. stream.Close();  
  28. }  
  29. }  
  30. public void Dispose()  
  31. {  
  32. Console.WriteLine("Dispose...");  
  33. }  
  34. }  
  35. public class WcfTest  
  36. {  
  37. public static void Test()  
  38. {  
  39. AppDomain.CreateDomain("Server").DoCallBack(delegate  
  40. {  
  41. ServiceHost host = new ServiceHost(typeof(FileService),   
  42. new Uri("http://localhost:8080/FileService"));  
  43. BasicHttpBinding binding = new BasicHttpBinding();  
  44. binding.TransferMode = TransferMode.Streamed;  
  45. host.AddServiceEndpoint(typeof(IFileService), binding, "");  
  46. host.Open();  
  47. });  
  48. BasicHttpBinding binding2 = new BasicHttpBinding();  
  49. binding2.TransferMode = TransferMode.Streamed;  
  50. IFileService channel = ChannelFactory.
    CreateChannel(binding2,   
  51. new EndpointAddress("http://localhost:8080/FileService"));  
  52. using (channel as IDisposable)  
  53. {  
  54. FileStream stream = new FileStream("MyLibrary2.dll", FileMode.Open);  
  55. channel.Test(stream);  
  56. stream.Close();  
  57. }  
  58. }  

 

一切正常。那么 "传递时消息体(Memory Body)中不能包含其他数据" 是什么意思?我们修改一下上面的契约,除了传递文件流外,我们还希望传递文件名。

 
 
 
  1. [ServiceContract]  
  2. public interface IFileService  
  3. {  
  4. [OperationContract]  
  5. void Upload(string filename, Stream stream);  
  6. }  
  7. // ... 其他代码暂略 ... 

 

当你修改完WCF传送二进制流数据的代码后,运行时你发现触发了一个 InvalidOperationException 异常。

未处理 System.InvalidOperationException
Message="For request in operation Upload to be a stream the operation must have a single parameter whose type is Stream."
Source="System.ServiceModel"

那么该怎么办呢?DataContract 肯定不行。 没错!你应该记得 MessageContract,将 filename 放到 MessageHeader 里面就行了。

 
 
 
  1. [MessageContract]  
  2. public class FileData  
  3. {  
  4. [MessageHeader]public string filename;  
  5. [MessageBodyMember]public Stream data;  
  6. }  
  7. [ServiceContract]  
  8. public interface IFileService  
  9. {  
  10. [OperationContract]  
  11. void Upload(FileData file);  
  12. }  
  13. public class FileService : IFileService, IDisposable  
  14. {  
  15. public void Upload(FileData file)  
  16. {  
  17. FileStream f = new FileStream(file.filename, FileMode.Create);  
  18. try  
  19. {  
  20. BinaryWriter writer = new BinaryWriter(f);  
  21. BinaryReader reader = new BinaryReader(file.data);  
  22. byte[] buffer;  
  23. do  
  24. {  
  25. buffer = reader.ReadBytes(1024);  
  26. writer.Write(buffer);  
  27. }  
  28. while (buffer.Length > 0);  
  29. }  
  30. finally  
  31. {  
  32. f.Close();  
  33. file.data.Close();  
  34. }  
  35. }  
  36. public void Dispose(){  
  37. Console.WriteLine("Dispose...");  
  38. }  
  39. }  
  40. public class WcfTest  
  41. {  
  42. public static void Test()  
  43. {  
  44. AppDomain.CreateDomain("Server").DoCallBack(delegate  
  45. {  
  46. ServiceHost host = new ServiceHost(typeof(FileService),   
  47. new Uri("http://localhost:8080/FileService"));  
  48. BasicHttpBinding binding = new BasicHttpBinding();  
  49. binding.TransferMode = TransferMode.Streamed;  
  50. host.AddServiceEndpoint(typeof(IFileService), binding, "");  
  51. host.Open();  
  52. });  
  53. BasicHttpBinding binding2 = new BasicHttpBinding();  
  54. binding2.TransferMode = TransferMode.Streamed;  
  55. IFileService channel = ChannelFactory.
    CreateChannel(binding2,   
  56. new EndpointAddress("http://localhost:8080/FileService"));  
  57. using (channel as IDisposable)  
  58. {  
  59. FileData file = new FileData();  
  60. file.filename = "test2.dll";  
  61. file.data = new FileStream("MyLibrary2.dll", FileMode.Open);  
  62. channel.Upload(file);  
  63. file.data.Close();  
  64. }  
  65. }  

 

问题解决了。上面的例子使用 BaseHttpBinding,如果使用 NetTcpBinding,相信速度要快很多。除了向服务器传送流外,也可反向返回流数据。

 
 
 
  1. [ServiceContract]  
  2. public interface IFileService  
  3. {  
  4. [OperationContract]  
  5. void Upload(Stream stream);  
  6. [OperationContract]  
  7. Stream Download(string filename);  

 

虽然服务器在操作结束时会自动关闭客户端 Request Stream,但个人建议还是使用 try...finnaly... 自主关闭要好一些,因为意外总是会发生的。

WCF传送二进制流数据的全部操作方法就为大家介绍到这里。

分享题目:WCF传送二进制流数据基本实现步骤详解
链接URL:http://www.shufengxianlan.com/qtweb/news19/527869.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联