【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); }
4.上面方法定義了輸入引數和返回引數,但是實際專案中往往是不夠的,我們需要增加其他引數,如檔名,檔案大小之類。然而WCF中有限定,如下:
保留要進行流處理的資料的引數必須是方法中的唯一引數。 例如,如果要對輸入訊息進行流處理,則該操作必須正好具有一個輸入引數。 同樣,如果要對輸出訊息進行流處理,則該操作必須正好具有一個輸出引數或一個返回值。
所以我們需要用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)等。最終程式碼如下:
<?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>
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); } } }
3.執行程式,上傳下載檔案,會在服務端和客服端執行目錄下分別找到上傳的檔案和下載的檔案,測試通過。介面如下:
小結
本文通過圖文一步步介紹瞭如何實現上傳下載檔案功能,其中涉及到WCF知識點其實是不少的,但是都是簡單地帶過。如果有不明白的地方,可以查閱Google,百度,也可以留言。如果您有更好的建議,請不吝指教,感激不盡!