利用WCF实现上传下载文件服务
2016-01-20 15:33
579 查看
本文是转载的,我根据本文的教程,成功写出来一个使用WCF上传和下载文件的程序,现在把原文和我自己写的项目全部上传过来
原文链接:点击打开链接
这是我写的例子的链接:github
引言
前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载。出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务。
服务端
1.首先新建一个名为FileService的WCF服务库项目,如下图:
![](http://images.cnitblog.com/blog2015/727285/201503/101535427775288.png)
2.将Service,IService重命名为FileService,IFileService,如下图:
![](http://images.cnitblog.com/blog2015/727285/201503/101540394803866.png)
3.打开IFileService.cs,定义两个方法,如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
View Code
4.上面方法定义了输入参数和返回参数,但是实际项目中往往是不够的,我们需要增加其他参数,如文件名,文件大小之类。然而WCF中有限定,如下:
保留要进行流处理的数据的参数必须是方法中的唯一参数。 例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。 同样,如果要对输出消息进行流处理,则该操作必须正好具有一个输出参数或一个返回值。
参数和返回值的类型中至少有一个必须是 Stream, Message 或 IXmlSerializable。
所以我们需要用Message契约特性包装一下参数,修改代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
View Code
5.现在服务契约定义好了,接下来实现契约的接口。打开FileService.cs文件,编写代码,实现服务端的上传下载文件服务,代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
View Code
6.至此,具体实现代码完成,但是我们还需要配置一下App.config,设置地址,契约和绑定。这里绑定采用NetTcpBinding,我们还需要为NetTcpBinding具体配置,如maxReceivedMessageSize(配置最大接收文件大小),transferMode(传输模式,这里是Streamed)等。最终代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
View Code
7.这时可以运行服务,如果没有问题的话,会看到如下截图。
![](http://images.cnitblog.com/blog2015/727285/201503/101610401361377.png)
客户端
1.首先新建一个WPF应用程序,在MainWindow.xaml添加控件,得到下图:
![](http://images.cnitblog.com/blog2015/727285/201503/101638310581820.png)
2.在引用中右击,选择添加服务引用,出现对话框,我们需要填上刚才打开的服务的地址,然后按旁边的转到,会看到显示找到服务,接着更改命名空间为FileService,得到如下图。
![](http://images.cnitblog.com/blog2015/727285/201503/101632374176212.png)
2.按确定之后,在资源管理器里的引用下面会多出一个FileService命名空间,里面包含我们的刚才写的FileServiceClient服务代理类 ,现在我们可以通过它调用服务了。编写代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
View Code
3.运行程序,上传下载文件,会在服务端和客服端运行目录下分别找到上传的文件和下载的文件,测试通过。界面如下:
![](http://images.cnitblog.com/blog2015/727285/201503/101647115113421.png)
![](http://images.cnitblog.com/blog2015/727285/201503/101647189641996.png)
小结
本文通过图文一步步介绍了如何实现上传下载文件功能,其中涉及到WCF知识点其实是不少的,但是都是简单地带过。如果有不明白的地方,可以查阅Google,百度,也可以留言。如果您有更好的建议,请不吝指教,感激不尽!
原文链接:点击打开链接
这是我写的例子的链接:github
引言
前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载。出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务。
服务端
1.首先新建一个名为FileService的WCF服务库项目,如下图:
![](http://images.cnitblog.com/blog2015/727285/201503/101535427775288.png)
2.将Service,IService重命名为FileService,IFileService,如下图:
![](http://images.cnitblog.com/blog2015/727285/201503/101540394803866.png)
3.打开IFileService.cs,定义两个方法,如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[ServiceContract] public interface IFileService { //上传文件 [OperationContract] bool UpLoadFile(Stream filestream); //下载文件 [OperationContract] Stream DownLoadFile(string downfile); }
View Code
4.上面方法定义了输入参数和返回参数,但是实际项目中往往是不够的,我们需要增加其他参数,如文件名,文件大小之类。然而WCF中有限定,如下:
保留要进行流处理的数据的参数必须是方法中的唯一参数。 例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。 同样,如果要对输出消息进行流处理,则该操作必须正好具有一个输出参数或一个返回值。
参数和返回值的类型中至少有一个必须是 Stream, Message 或 IXmlSerializable。
所以我们需要用Message契约特性包装一下参数,修改代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[ServiceContract] public interface IFileService { //上传文件 [OperationContract] UpFileResult UpLoadFile(UpFile filestream); //下载文件 [OperationContract] DownFileResult DownLoadFile(DownFile downfile); } [MessageContract] public class DownFile { [MessageHeader] public string FileName { get; set; } } [MessageContract] public class UpFileResult { [MessageHeader] public bool IsSuccess { get; set; } [MessageHeader] public string Message { get; set; } } [MessageContract] public class UpFile { [MessageHeader] public long FileSize { get; set; } [MessageHeader] public string FileName { get; set; } [MessageBodyMember] public Stream FileStream { get; set; } } [MessageContract] public class DownFileResult { [MessageHeader] public long FileSize { get; set; } [MessageHeader] public bool IsSuccess { get; set; } [MessageHeader] public string Message { get; set; } [MessageBodyMember] public Stream FileStream { get; set; } }
View Code
5.现在服务契约定义好了,接下来实现契约的接口。打开FileService.cs文件,编写代码,实现服务端的上传下载文件服务,代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class FileService : IFileService { public UpFileResult UpLoadFile(UpFile filedata) { UpFileResult result = new UpFileResult(); string path = System.AppDomain.CurrentDomain.BaseDirectory +@"\service\"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } byte[] buffer = new byte[filedata.FileSize]; FileStream fs = new FileStream(path + filedata.FileName, FileMode.Create, FileAccess.Write); int count = 0; while ((count = filedata.FileStream.Read(buffer, 0, buffer.Length)) > 0) { fs.Write(buffer, 0, count); } //清空缓冲区 fs.Flush(); //关闭流 fs.Close(); result.IsSuccess = true; return result; } //下载文件 public DownFileResult DownLoadFile(DownFile filedata) { DownFileResult result = new DownFileResult(); string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\service\" + filedata.FileName; if (!File.Exists(path)) { result.IsSuccess = false; result.FileSize = 0; result.Message = "服务器不存在此文件"; result.FileStream = new MemoryStream(); return result; } Stream ms = new MemoryStream(); FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); fs.CopyTo(ms); ms.Position = 0; //重要,不为0的话,客户端读取有问题 result.IsSuccess = true; result.FileSize = ms.Length; result.FileStream = ms; fs.Flush(); fs.Close(); return result; } }
View Code
6.至此,具体实现代码完成,但是我们还需要配置一下App.config,设置地址,契约和绑定。这里绑定采用NetTcpBinding,我们还需要为NetTcpBinding具体配置,如maxReceivedMessageSize(配置最大接收文件大小),transferMode(传输模式,这里是Streamed)等。最终代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" /> </system.web> <!-- 部署服务库项目时,必须将配置文件的内容添加到 主机的 app.config 文件中。System.Configuration 不支持库的配置文件。--> <system.serviceModel> <bindings> <netTcpBinding> <binding name="MyTcpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="00:30:00" transferMode="Streamed" > <security mode="None"></security> </binding> </netTcpBinding> </bindings> <services> <service name="WcfTest.FileService"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="MyTcpBinding" contract="WcfTest.IFileService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfTest/Service1/" /> <add baseAddress="net.tcp://localhost:8734/Design_Time_Addresses/WcfTest/Service1/" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息, 请在部署前将以下值设置为 false --> <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/> <!-- 要接收故障异常详细信息以进行调试, 请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息--> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
View Code
7.这时可以运行服务,如果没有问题的话,会看到如下截图。
![](http://images.cnitblog.com/blog2015/727285/201503/101610401361377.png)
客户端
1.首先新建一个WPF应用程序,在MainWindow.xaml添加控件,得到下图:
![](http://images.cnitblog.com/blog2015/727285/201503/101638310581820.png)
2.在引用中右击,选择添加服务引用,出现对话框,我们需要填上刚才打开的服务的地址,然后按旁边的转到,会看到显示找到服务,接着更改命名空间为FileService,得到如下图。
![](http://images.cnitblog.com/blog2015/727285/201503/101632374176212.png)
2.按确定之后,在资源管理器里的引用下面会多出一个FileService命名空间,里面包含我们的刚才写的FileServiceClient服务代理类 ,现在我们可以通过它调用服务了。编写代码如下:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public partial class MainWindow : Window { FileServiceClient client; public MainWindow() { InitializeComponent(); client = new FileServiceClient(); } private void Button_Click_1(object sender, RoutedEventArgs e) { OpenFileDialog Fdialog = new OpenFileDialog(); if (Fdialog.ShowDialog().Value) { using (Stream fs = new FileStream(Fdialog.FileName, FileMode.Open, FileAccess.Read)) { string message; this.filepath.Text = Fdialog.SafeFileName; bool result = client.UpLoadFile(Fdialog.SafeFileName, fs.Length,fs, out message); if (result == true) { MessageBox.Show("上传成功!"); } else { MessageBox.Show(message); } } } } private void Button_Click_2(object sender, RoutedEventArgs e) { string filename = this.filename.Text; string path = System.AppDomain.CurrentDomain.BaseDirectory + @"\client\"; bool issuccess=false; string message=""; Stream filestream=new MemoryStream(); long filesize = client.DownLoadFile(filename, out issuccess, out message, out filestream); if (issuccess) { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } byte[] buffer = new byte[filesize]; FileStream fs = new FileStream(path + filename, FileMode.Create, FileAccess.Write); int count = 0; while ((count = filestream.Read(buffer, 0, buffer.Length)) > 0) { fs.Write(buffer, 0, count); } //清空缓冲区 fs.Flush(); //关闭流 fs.Close(); MessageBox.Show("下载成功!"); } else { MessageBox.Show(message); } } }
View Code
3.运行程序,上传下载文件,会在服务端和客服端运行目录下分别找到上传的文件和下载的文件,测试通过。界面如下:
![](http://images.cnitblog.com/blog2015/727285/201503/101647115113421.png)
![](http://images.cnitblog.com/blog2015/727285/201503/101647189641996.png)
小结
本文通过图文一步步介绍了如何实现上传下载文件功能,其中涉及到WCF知识点其实是不少的,但是都是简单地带过。如果有不明白的地方,可以查阅Google,百度,也可以留言。如果您有更好的建议,请不吝指教,感激不尽!
相关文章推荐
- oracle利用游标数据初始化
- hadoop入门编程
- 本机操作Excel文件提示错误:未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序。
- eclipse代码生成器
- mongoDB入门必读
- iOS应用架构谈(二):View层的组织和调用方案(上)
- sun.misc.BASE64Encoder找不到的解决方法
- Fragment状态的保存
- MAC OS中使用ll,la命令
- C语言再学习之进制转换总结
- VS 2012 添加Web引用
- java_listener监听器教程及实例
- 正则表达式限制 账号 密码 邮箱 身份证 手机号的相关代码
- 手机web——自适应网页设计(html/css控制)
- Android得到视频缩略图
- Linux系统文件I/O编程(一)---open()等基本函数
- 讯飞开放平台上线业界首个多生物特征融合认证方案
- PHP curl_setopt函数用法介绍上篇
- LU 分解,采用行连续划分方式下的 MPI 实现
- MFC学习(24)线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法