天天看點

上接穩紮穩打Silverlight(20) - 2.0通信之WebClient, 以字元串的形式上傳/下載下傳資料

2、以字元串的形式和流的形式上傳資料

REST.cs(WCF建立的用于示範以字元串的形式和流的形式上傳資料的REST服務)

using System; 

using System.Linq; 

using System.Runtime.Serialization; 

using System.ServiceModel; 

using System.ServiceModel.Activation; 

using System.ServiceModel.Web; 

using System.Collections.Generic; 

using System.Text; 

using System.IO; 

/// <summary> 

/// 提供 REST 服務的類 

/// 注:Silverlight隻支援 GET 和 POST 

/// </summary> 

[ServiceContract] 

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 

public class REST 

        /// <summary> 

        /// 用于示範傳回 JSON(對象) 的 REST 服務 

        /// </summary> 

        /// <param name="name"></param> 

        /// <returns></returns> 

        [OperationContract] 

        [WebGet(UriTemplate = "User/{name}/json", ResponseFormat = WebMessageFormat.Json)] 

        public User HelloJson(string name) 

        { 

                return new User { Name = name, DayOfBirth = new DateTime(1980, 2, 14) }; 

        } 

        /// 用于示範傳回 JSON(集合) 的 REST 服務 

        [WebGet(UriTemplate = "Users/json", ResponseFormat = WebMessageFormat.Json)] 

        public List<User> HelloJson2() 

                return new List<User>    

                {    

                        new User(){ Name = "webabcd01", DayOfBirth = new DateTime(1980, 1, 1) }, 

                        new User(){ Name = "webabcd02", DayOfBirth = new DateTime(1980, 2, 2) }, 

                        new User(){ Name = "webabcd03", DayOfBirth = new DateTime(1980, 3, 3) }, 

                }; 

        /// 用于示範傳回 XML(對象) 的 REST 服務 

        [WebGet(UriTemplate = "User/{name}/xml", ResponseFormat = WebMessageFormat.Xml)] 

        public User HelloXml(string name) 

        /// 用于示範傳回 XML(集合) 的 REST 服務 

        [WebGet(UriTemplate = "Users/xml", ResponseFormat = WebMessageFormat.Xml)] 

        public List<User> HelloXml2() 

        /// 用于示範以字元串的形式上傳資料的 REST 服務 

        /// <param name="fileName">上傳的檔案名</param> 

        /// <param name="stream">POST 過來的資料</param> 

        [WebInvoke(UriTemplate = "UploadString/?fileName={fileName}", Method = "POST", ResponseFormat = WebMessageFormat.Json)] 

        public bool UploadString(string fileName, Stream stream) 

                // 檔案的服務端儲存路徑 

                string path = Path.Combine("C:\\", fileName); 

                try 

                { 

                        using (StreamReader sr = new StreamReader(stream)) 

                        { 

                                // 将 POST 過來的被 Base64 編碼過字元串傳換成 byte[] 

                                byte[] buffer = Convert.FromBase64String(sr.ReadToEnd()); 

                                using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) 

                                { 

                                        // 将檔案寫入到服務端 

                                        fs.Write(buffer, 0, buffer.Length); 

                                } 

                        } 

                        return true; 

                } 

                catch 

                        return false; 

        /// 用于示範以流的形式上傳資料的 REST 服務 

        /// <param name="stream">POST 過來的資料(流的方式)</param> 

        [WebInvoke(UriTemplate = "UploadStream/?fileName={fileName}", Method = "POST", ResponseFormat = WebMessageFormat.Json)] 

        public bool UploadStream(string fileName, Stream stream) 

                        using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) 

                                byte[] buffer = new byte[4096]; 

                                int count = 0; 

                                // 每 POST 過來 4096 位元組的資料,往服務端寫一次 

                                while ((count = stream.Read(buffer, 0, buffer.Length)) > 0) 

                                        fs.Write(buffer, 0, count); 

}

WebClientUpload.xaml

<UserControl x:Class="Silverlight20.Communication.WebClientUpload" 

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

        <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">             

                <StackPanel Margin="5" Width="200"> 

                        <TextBox x:Name="lblMsgString" Margin="5" /> 

                        <ProgressBar x:Name="progressBarString" Height="20" Margin="5" Minimum="0" Maximum="100" /> 

                        <Button x:Name="btnString" Content="上傳檔案(字元串的方式)" Margin="5" Click="btnString_Click" /> 

                </StackPanel> 

                        <TextBox x:Name="lblMsgStream" Margin="5" /> 

                        <ProgressBar x:Name="progressBarStream" Height="20" Margin="5" Minimum="0" Maximum="100" /> 

                        <Button x:Name="btnStream" Content="上傳檔案(流的方式)" Margin="5" Click="btnStream_Click" /> 

        </StackPanel> 

</UserControl>

WebClientUpload.xaml.cs

using System.Net; 

using System.Windows; 

using System.Windows.Controls; 

using System.Windows.Documents; 

using System.Windows.Input; 

using System.Windows.Media; 

using System.Windows.Media.Animation; 

using System.Windows.Shapes; 

using System.Windows.Resources; 

using System.ComponentModel; 

using System.Windows.Browser; 

namespace Silverlight20.Communication 

        public partial class WebClientUpload : UserControl 

                // 用于示範以字元串的形式上傳資料 

                string _urlString = "http://localhost:3036/REST.svc/UploadString/?fileName="; 

                // 用于示範以流的形式上傳資料 

                string _urlStream = "http://localhost:3036/REST.svc/UploadStream/?fileName="; 

                public WebClientUpload() 

                        InitializeComponent(); 

                /// <summary> 

                /// 示範字元串式上傳 

                /// </summary> 

                /// <param name="sender"></param> 

                /// <param name="e"></param> 

                private void btnString_Click(object sender, RoutedEventArgs e) 

                        string data = ""; 

                        /* 

                         * OpenFileDialog - 檔案對話框 

                         *         ShowDialog() - 顯示檔案對話框。在檔案對話框中單擊“确定”則傳回true,反之則傳回false 

                         *         File - 所選檔案的 FileInfo 對象 

                         */ 

                        OpenFileDialog dialog = new OpenFileDialog(); 

                        if (dialog.ShowDialog() == true) 

                                using (FileStream fs = dialog.File.OpenRead()) 

                                        byte[] buffer = new byte[fs.Length]; 

                                        fs.Read(buffer, 0, buffer.Length); 

                                        // 将指定的 byte[] 轉換為字元串(使用Base64編碼) 

                                        data = Convert.ToBase64String(buffer); 

                                /* 

                                 * WebClient - 将資料發送到指定的 URI,或者從指定的 URI 接收資料的類 

                                 *         UploadStringCompleted - 上傳資料完畢後(包括取消操作及有錯誤發生時)所觸發的事件 

                                 *         UploadProgressChanged - 上傳資料過程中所觸發的事件。正在上傳或上傳完全部資料後會觸發 

                                 *         Headers - 與請求相關的的标頭的 key/value 對集合 

                                 *         UploadStringAsync(Uri address, string data) - 以字元串的形式上傳資料到指定的 URI。所使用的 HTTP 方法預設為 POST 

                                 *                 Uri address - 接收上傳資料的 URI 

                                 *                 string data - 需要上傳的資料 

                                 */ 

                                System.Net.WebClient clientUploadString = new System.Net.WebClient(); 

                                clientUploadString.UploadStringCompleted += new UploadStringCompletedEventHandler(clientUploadString_UploadStringCompleted); 

                                clientUploadString.UploadProgressChanged += new UploadProgressChangedEventHandler(clientUploadString_UploadProgressChanged); 

                                Uri uri = new Uri(_urlString + dialog.File.Name, UriKind.Absolute); 

                                clientUploadString.Headers["Content-Type"] = "application/x-www-form-urlencoded"; 

                                clientUploadString.UploadStringAsync(uri, data); 

                void clientUploadString_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)

                         * UploadProgressChangedEventArgs.ProgressPercentage - 上傳完成的百分比 

                         * UploadProgressChangedEventArgs.BytesSent - 目前發送的位元組數 

                         * UploadProgressChangedEventArgs.TotalBytesToSend - 總共需要發送的位元組數 

                         * UploadProgressChangedEventArgs.BytesReceived - 目前接收的位元組數 

                         * UploadProgressChangedEventArgs.TotalBytesToReceive - 總共需要接收的位元組數 

                         * UploadProgressChangedEventArgs.UserState - 使用者辨別 

                        lblMsgString.Text = string.Format("上傳完成的百分比:{0}\r\n目前發送的位元組數:{1}\r\n總共需要發送的位元組數:{2}\r\n目前接收的位元組數:{3}\r\n總共需要接收的位元組數:{4}\r\n", 

                                e.ProgressPercentage.ToString(), 

                                e.BytesSent.ToString(), 

                                e.TotalBytesToSend.ToString(), 

                                e.BytesReceived.ToString(), 

                                e.TotalBytesToReceive.ToString()); 

                        progressBarString.Value = (double)e.ProgressPercentage; 

                void clientUploadString_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e) 

                         * UploadStringCompletedEventArgs.Error - 該異步操作期間是否發生了錯誤 

                         * UploadStringCompletedEventArgs.Cancelled - 該異步操作是否已被取消 

                         * UploadStringCompletedEventArgs.Result - 服務端傳回的資料(字元串類型) 

                         * UploadStringCompletedEventArgs.UserState - 使用者辨別 

                        if (e.Error != null) 

                                lblMsgString.Text += e.Error.ToString(); 

                                return; 

                        if (e.Cancelled != true) 

                                var jsonObject = System.Json.JsonObject.Parse(e.Result); 

                                lblMsgString.Text += string.Format("是否上傳成功:{0}", 

                                        (bool)jsonObject); 

                /// 示範流式上傳 

                private void btnStream_Click(object sender, RoutedEventArgs e) 

                        FileStream fs = null; 

                                fs = dialog.File.OpenRead(); 

                                 *         OpenWriteCompleted - 在打開用于上傳的流完成時(包括取消操作及有錯誤發生時)所觸發的事件 

                                 *         WriteStreamClosed - 在寫入資料流的異步操作完成時(包括取消操作及有錯誤發生時)所觸發的事件 

                                 *         UploadProgressChanged - 上傳資料過程中所觸發的事件。如果調用 OpenWriteAsync() 則不會觸發此事件 

                                 *         OpenWriteAsync(Uri address, string method, Object userToken) - 打開流以使用指定的方法向指定的 URI 寫入資料 

                                 *                 string method - 所使用的 HTTP 方法(POST 或 GET) 

                                 *                 Object userToken - 需要上傳的資料流 

                                System.Net.WebClient clientUploadStream = new System.Net.WebClient(); 

                                clientUploadStream.OpenWriteCompleted += new OpenWriteCompletedEventHandler(clientUploadStream_OpenWriteCompleted); 

                                clientUploadStream.UploadProgressChanged += new UploadProgressChangedEventHandler(clientUploadStream_UploadProgressChanged); 

                                clientUploadStream.WriteStreamClosed += new WriteStreamClosedEventHandler(clientUploadStream_WriteStreamClosed); 

                                Uri uri = new Uri(_urlStream + dialog.File.Name, UriKind.Absolute); 

                                clientUploadStream.Headers["Content-Type"] = "multipart/form-data"; 

                                clientUploadStream.OpenWriteAsync(uri, "POST", fs); 

                void clientUploadStream_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) 

                        // 因為是調用 OpenWriteAsync(),是以不會觸發 UploadProgressChanged 事件 

                        progressBarStream.Value = (double)e.ProgressPercentage; 

                void clientUploadStream_OpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e) 

                        System.Net.WebClient client = sender as System.Net.WebClient; 

                                lblMsgStream.Text += e.Error.ToString(); 

                                // e.UserState - 需要上傳的流(用戶端流) 

                                Stream clientStream = e.UserState as Stream; 

                                // e.Result - 目标位址的流(服務端流) 

                                Stream serverStream = e.Result; 

                                // clientStream.Read - 将需要上傳的流讀取到指定的位元組數組中 

                                while ((count = clientStream.Read(buffer, 0, buffer.Length)) > 0) 

                                        // serverStream.Write - 将指定的位元組數組寫入到目标位址的流 

                                        serverStream.Write(buffer, 0, count); 

                                serverStream.Close(); 

                                clientStream.Close(); 

                void clientUploadStream_WriteStreamClosed(object sender, WriteStreamClosedEventArgs e) 

                        else 

                                lblMsgStream.Text += "上傳完成"; 

/* 

 * 其他: 

 * 1、WebClient 對象一次隻能啟動一個請求。如果在一個請求完成(包括出錯和取消)前,即IsBusy為true時,進行第二個請求,則第二個請求将會抛出 NotSupportedException 類型的異常 

 * 2、如果 WebClient 對象的 BaseAddress 屬性不為空,則 BaseAddress 與 URI(相對位址) 組合在一起構成絕對 URI 

 * 3、WebClient 類的 AllowReadStreamBuffering 屬性:是否對從 Internet 資源接收的資料做緩沖處理。預設值為true,将資料緩存在用戶端記憶體中,以便随時被應用程式讀取 

 */

OK

<a href="http://down.51cto.com/data/100302" target="_blank">[源碼下載下傳]</a>

     本文轉自webabcd 51CTO部落格,原文連結:http://blog.51cto.com/webabcd/343126,如需轉載請自行聯系原作者