利用WCF实现上传下载文件服务

引言

    前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载。出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务。

服务端

      1.首先新建一个名为FileService的WCF服务库项目,如下图:

       技术分享

      2.将Service,IService重命名为FileService,IFileService,如下图:

        技术分享

      3.打开IFileService.cs,定义两个方法,如下:

   [ServiceContract]

    public interfaceIFileService

    {

 

       //上传文件

       [OperationContract]

       bool UpLoadFile(Stream filestream);

 

       //下载文件

       [OperationContract]

       Stream DownLoadFile(string downfile);

 

    }

View Code

     4.上面方法定义了输入参数和返回参数,但是实际项目中往往是不够的,我们需要增加其他参数,如文件名,文件大小之类。然而WCF中有限定,如下:

o   保留要进行流处理的数据的参数必须是方法中的唯一参数。 例如,如果要对输入消息进行流处理,则该操作必须正好具有一个输入参数。 同样,如果要对输出消息进行流处理,则该操作必须正好具有一个输出参数或一个返回值。

o   参数和返回值的类型中至少有一个必须是 StreamMessage 或 IXmlSerializable

     所以我们需要用Message契约特性包装一下参数,修改代码如下:

   [ServiceContract]

    public interfaceIFileService

    {

       //上传文件

       [OperationContract]

       UpFileResult UpLoadFile(UpFile filestream);

 

       //下载文件

       [OperationContract]

       DownFileResult DownLoadFile(DownFile downfile);

    }

 

   [MessageContract]

    public class DownFile

    {

       [MessageHeader]

       public string FileName { get; set; }

    }

 

   [MessageContract]

    public classUpFileResult

    {

       [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 classDownFileResult

    {

       [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文件,编写代码,实现服务端的上传下载文件服务,代码如下:

 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>

    <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.这时可以运行服务,如果没有问题的话,会看到如下截图。

   技术分享

客户端

  1.首先新建一个WPF应用程序,在MainWindow.xaml添加控件,得到下图:

      技术分享

     2.在引用中右击,选择添加服务引用,出现对话框,我们需要填上刚才打开的服务的地址,然后按旁边的转到,会看到显示找到服务,接着更改命名空间为FileService,得到如下图。

     技术分享

    2.按确定之后,在资源管理器里的引用下面会多出一个FileService命名空间,里面包含我们的刚才写的FileServiceClient服务代理类 ,现在我们可以通过它调用服务了。编写代码如下:

  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 = 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);

                    }

                }

 

            }

       }

 

       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, 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,百度,也可以留言。如果您有更好的建议,请不吝指教,感激不尽!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值