引言

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

服务端

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

       

微服务文件传输_下载文件

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

        

微服务文件传输_WCF_02

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

[ServiceContract]
    public interface IFileService
    {

        //上传文件
        [OperationContract]
        bool UpLoadFile(Stream filestream);

        //下载文件
        [OperationContract]
        Stream DownLoadFile(string downfile); 
  
    }



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

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

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

[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; }
    }

    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 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;
        }
    }

    6.至此,具体实现代码完成,但是我们还需要配置一下App.config,设置地址,契约和绑定。这里绑定采用NetTcpBinding,我们还需要为NetTcpBinding具体配置,如maxReceivedMessageSize(配置最大接收文件大小),transferMode(传输模式,这里是Streamed)等。最终代码如下:


    7.这时可以运行服务,如果没有问题的话,会看到如下截图。

   

微服务文件传输_微服务文件传输_03

客户端

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

      

微服务文件传输_微服务文件传输_04

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

     

微服务文件传输_下载文件_05

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


   3.运行程序,上传下载文件,会在服务端和客服端运行目录下分别找到上传的文件和下载的文件,测试通过。界面如下:

   

微服务文件传输_WCF_06

微服务文件传输_WCF_07

小结

 本文通过图文一步步介绍了如何实现上传下载文件功能,其中涉及到WCF知识点其实是不少的,但是都是简单地带过。如果有不明白的地方,可以查阅Google,百度,也可以留言。如果您有更好的建议,请不吝指教,感激不尽!