利用WCF实现上传下载文件服务
来源:互联网 发布:360软件应用商店 编辑:程序博客网 时间:2024/05/29 16:30
引言
前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载。出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务。
服务端
1.首先新建一个名为FileService的WCF服务库项目,如下图:
2.将Service,IService重命名为FileService,IFileService,如下图:
3.打开IFileService.cs,定义两个方法,如下:
[ServiceContract]
publicinterfaceIFileService
{
//上传文件
[OperationContract]
bool UpLoadFile(Stream filestream);
//下载文件
[OperationContract]
Stream DownLoadFile(string downfile);
}
View Code
4.上面方法定义了输入参数和返回参数,但是实际项目中往往是不够的,我们需要增加其他参数,如文件名,文件大小之类。然而WCF中有限定,如下:
o 保留要进行流处理的数据的参数必须是方法中的唯一参数。 例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。 同样,如果要对输出消息进行流处理,则该操作必须正好具有一个输出参数或一个返回值。
o 参数和返回值的类型中至少有一个必须是 Stream, Message 或 IXmlSerializable。
所以我们需要用Message契约特性包装一下参数,修改代码如下:
[ServiceContract]
publicinterfaceIFileService
{
//上传文件
[OperationContract]
UpFileResult UpLoadFile(UpFile filestream);
//下载文件
[OperationContract]
DownFileResult DownLoadFile(DownFile downfile);
}
[MessageContract]
publicclass DownFile
{
[MessageHeader]
publicstring FileName { get;set; }
}
[MessageContract]
publicclassUpFileResult
{
[MessageHeader]
publicbool IsSuccess { get;set; }
[MessageHeader]
publicstring Message { get;set; }
}
[MessageContract]
publicclass UpFile
{
[MessageHeader]
publiclong FileSize { get;set; }
[MessageHeader]
publicstring FileName { get;set; }
[MessageBodyMember]
public Stream FileStream {get;set; }
}
[MessageContract]
publicclassDownFileResult
{
[MessageHeader]
publiclong FileSize { get;set; }
[MessageHeader]
publicbool IsSuccess { get;set; }
[MessageHeader]
publicstring Message { get;set; }
[MessageBodyMember]
public Stream FileStream {get;set; }
}
View Code
5.现在服务契约定义好了,接下来实现契约的接口。打开FileService.cs文件,编写代码,实现服务端的上传下载文件服务,代码如下:
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 DownFileResultDownLoadFile(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();
returnresult;
}
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)等。最终代码如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<addkey="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilationdebug="true"/>
</system.web>
<!-- 部署服务库项目时,必须将配置文件的内容添加到
主机的 app.config文件中。System.Configuration 不支持库的配置文件。-->
<system.serviceModel>
<bindings>
<netTcpBinding>
<bindingname="MyTcpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" sendTimeout="00:30:00" transferMode="Streamed" >
<securitymode="None"></security>
</binding>
</netTcpBinding>
</bindings>
<services>
<servicename="WcfTest.FileService">
<endpointaddress="" binding="netTcpBinding" bindingConfiguration="MyTcpBinding" contract="WcfTest.IFileService">
<identity>
<dnsvalue="localhost"/>
</identity>
</endpoint>
<endpointaddress="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<addbaseAddress="http://localhost:8733/Design_Time_Addresses/WcfTest/Service1/"/>
<addbaseAddress="net.tcp://localhost:8734/Design_Time_Addresses/WcfTest/Service1/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false -->
<serviceMetadatahttpGetEnabled="True" httpsGetEnabled="True"/>
<!-- 要接收故障异常详细信息以进行调试,
请将以下值设置为 true。在部署前设置为 false
以避免泄漏异常信息-->
<serviceDebugincludeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
View Code
7.这时可以运行服务,如果没有问题的话,会看到如下截图。
客户端
1.首先新建一个WPF应用程序,在MainWindow.xaml添加控件,得到下图:
2.在引用中右击,选择添加服务引用,出现对话框,我们需要填上刚才打开的服务的地址,然后按旁边的转到,会看到显示找到服务,接着更改命名空间为FileService,得到如下图。
2.按确定之后,在资源管理器里的引用下面会多出一个FileService命名空间,里面包含我们的刚才写的FileServiceClient服务代理类 ,现在我们可以通过它调用服务了。编写代码如下:
public partial class MainWindow : Window
{
FileServiceClient client;
public MainWindow()
{
InitializeComponent();
client = new FileServiceClient();
}
privatevoid Button_Click_1(object sender,RoutedEventArgs e)
{
OpenFileDialog Fdialog =new OpenFileDialog();
if (Fdialog.ShowDialog().Value)
{
using (Stream fs =newFileStream(Fdialog.FileName, FileMode.Open, FileAccess.Read))
{
stringmessage;
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);
}
}
}
}
privatevoid 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, outmessage,outfilestream);
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.运行程序,上传下载文件,会在服务端和客服端运行目录下分别找到上传的文件和下载的文件,测试通过。界面如下:
小结
本文通过图文一步步介绍了如何实现上传下载文件功能,其中涉及到WCF知识点其实是不少的,但是都是简单地带过。如果有不明白的地方,可以查阅Google,百度,也可以留言。如果您有更好的建议,请不吝指教,感激不尽!
- 【WCF】利用WCF实现上传下载文件服务
- 【WCF】利用WCF实现上传下载文件服务
- 利用WCF实现上传下载文件服务
- 利用WCF实现上传下载文件服务
- JSP利用SmartUpload组件实现文件上传下载
- 浅谈利用jspsmart实现文件上传下载(转)
- 利用FTPClient类实现文件的上传下载功能
- 利用FtpClient类实现文件的上传下载功能
- 利用FtpClient实现上传下载及获得文件目录
- 利用FTPClient类实现文件的上传下载功能
- jsp中如何利用jspsmartupload实现文件上传下载功能
- JCIFS简介and利用JCIFS网络文件共享实现上传下载
- 【前端】利用ajax实现伪文件异步上传下载
- WCF实现REST服务
- jspsmart实现文件上传下载
- jspsmart实现文件上传下载
- c#实现文件上传下载
- jspSmartUpload 实现文件上传下载
- 第八周上机实践项目——项目1-数组作数据成员
- Java中HashMap详解
- MAC上安装brew,安装wget
- 飞思卡尔的i.mx6dl开发板上实现nfs网络文件系统挂载操作指南
- JAVA使用JDBC连接MySQL数据库
- 利用WCF实现上传下载文件服务
- uva 10304 - Optimal Binary Search Tree(区间dp)
- 【BZOJ1901】Zju2112 Dynamic Rankings【树状数组套主席树 / 整体二分】
- 【项目管理】优秀项目经理必知的六大沟通技巧
- Python Decorator 3: 嵌套
- 超越sublime的Visual Studio Code
- 笔试题29. LeetCode OJ (16)
- centos 64 安装mongodb
- 论dts中的of_platform_populate如何选择性加载device node为platform device