【WCF】利用WCF實現上傳下載文件服務


引言

    前段時間,用WCF做了一個小項目,其中涉及到文件的上傳下載。出於復習鞏固的目的,今天簡單梳理了一下,整理出來,下面展示如何一步步實現一個上傳下載的WCF服務。

服務端

      1.首先新建一個名為FileService的WCF服務庫項目,如下圖:

       

      2.將Service,IService重命名為FileService,IFileService,如下圖:

        

      3.打開IFileService.cs,定義兩個方法,如下:

    [ServiceContract]
    public interface IFileService
    {

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

        //下載文件
        [OperationContract]
        Stream DownLoadFile(string downfile); 
  
    }
View Code

     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; }
    }
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 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)等。最終代碼如下:

<?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 = 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.運行程序,上傳下載文件,會在服務端和客服端運行目錄下分別找到上傳的文件和下載的文件,測試通過。界面如下:

   

小結

  本文通過圖文一步步介紹了如何實現上傳下載文件功能,其中涉及到WCF知識點其實是不少的,但是都是簡單地帶過。如果有不明白的地方,可以查閱Google,百度,也可以留言。如果您有更好的建議,請不吝指教,感激不盡!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM