SilverLight学习笔记--使用WebClient实现通讯(二)(上传和下载流数据)

   接上节,本文直接进入实例操作部分。在此处,我们以典型的图片文件为例来学习如何用WebClient类来实现上传和下载流数据的。
   新建一个Silverlight应用程序,命名为:SLWebClientStream。
   一、准备工作:
   1、准备一张图片,本例我们准备了一张名为Bubble.jpg的图片,把它拷贝到SLWebClientStream.Web项目的根目录下。
   2、在SLWebClientStream.Web项目下新建一个目录,命名为Pics,我们将在此处放置上传上来的图片文件。
   完成准备工作后,项目如下图:
 

                          

二、编码实现

 
 (一)、客户端部分
 1、建立用户界面
 Page.xaml内容如下:

 

< UserControl x:Class = " SLWebClientStream.Page "
    xmlns
= " http://schemas.microsoft.com/winfx/2006/xaml/presentation "  
    xmlns:x
= " http://schemas.microsoft.com/winfx/2006/xaml "  
    Width
= " 500 "  Height = " 450 " >
    
< StackPanel Background = " White "  Height = " 450 " >
        
< TextBlock x:Name = " tbMsgString "  Text = " 下载进度 "  TextAlignment = " Center "  Foreground = " Green " ></ TextBlock >
        
< Button x:Name = " btnDownload "  Content = " DownLoad Pictures "  Width = " 150 "  Height = " 35 "  Margin = " 15 "  Click = " btnDownload_Click " />
        
< Border Background = " Wheat "  BorderThickness = " 5 "  Width = " 400 "  Height = " 280 " >
            
< Image x:Name = " imgDownLoad "  Width = " 400 "  Height = " 300 "  Margin = " 15 "  Stretch = " Fill " />
        
</ Border >
        
< Button x:Name = " btnUpLoad "  Content = " UpLoad Pictures "  Width = " 150 "  Height = " 35 "  Margin = " 15 "  Click = " btnUpLoad_Click " />
    
</ StackPanel >
</ UserControl >

 界面如下:


                         
2、下载图片文件代码


         #region   下载图片
        
private   void  btnDownload_Click( object  sender, RoutedEventArgs e)
        {
            
// 向指定的Url发送下载流数据请求 
            String imgUrl  =   " http://localhost:51896/Bubble.jpg " ;     
             Uri endpoint 
=   new  Uri(imgUrl);

            WebClient client 
=   new  WebClient();
            client.OpenReadCompleted 
+=   new  OpenReadCompletedEventHandler(OnOpenReadCompleted);
            client.DownloadProgressChanged 
+=   new  DownloadProgressChangedEventHandler(clientDownloadStream_DownloadProgressChanged);
            client.OpenReadAsync(endpoint);
        }
        
void  OnOpenReadCompleted( object  sender,OpenReadCompletedEventArgs e)
        {
 
             
// OpenReadCompletedEventArgs.Error - 该异步操作期间是否发生了错误
             
// OpenReadCompletedEventArgs.Cancelled - 该异步操作是否已被取消
             
// OpenReadCompletedEventArgs.Result - 下载后的 Stream 类型的数据
             
// OpenReadCompletedEventArgs.UserState - 用户标识
 
            
if  (e.Error  !=   null )
            {
                MessageBox.Show(e.Error.ToString());
                
return ;
            }
            
if  (e.Cancelled  !=   true )
            {
                
// 获取下载的流数据(在此处是图片数据)并显示在图片控件中
                Stream stream  =  e.Result;
                BitmapImage bitmap 
=   new  BitmapImage();
                bitmap.SetSource(stream);
                imgDownLoad.Source 
=  bitmap;
            }



        }

        
void  clientDownloadStream_DownloadProgressChanged( object  sender, DownloadProgressChangedEventArgs e)
        {
            
// DownloadProgressChangedEventArgs.ProgressPercentage - 下载完成的百分比
            
// DownloadProgressChangedEventArgs.BytesReceived - 当前收到的字节数
            
// DownloadProgressChangedEventArgs.TotalBytesToReceive - 总共需要下载的字节数
            
// DownloadProgressChangedEventArgs.UserState - 用户标识
        
            
this .tbMsgString.Text  =   string .Format( " 完成百分比:{0} 当前收到的字节数:{1} 资料大小:{2}  " ,
              e.ProgressPercentage.ToString() 
+   " % " ,
              e.BytesReceived.ToString(),
              e.TotalBytesToReceive.ToString());

        }

        
#endregion

 3、上传图片文件代码


     #region   上传图片
        
private   void  btnUpLoad_Click( object  sender, RoutedEventArgs e)
        {
            
/*
             *   OpenWriteCompleted - 在打开用于上传的流完成时(包括取消操作及有错误发生时)所触发的事件
             *   WriteStreamClosed - 在写入数据流的异步操作完成时(包括取消操作及有错误发生时)所触发的事件
             *   UploadProgressChanged - 上传数据过程中所触发的事件。如果调用 OpenWriteAsync() 则不会触发此事件
             *   Headers - 与请求相关的的标头的 key/value 对**
             *   OpenWriteAsync(Uri address, string method, Object userToken) - 打开流以使用指定的方法向指定的 URI 写入数据
             *     Uri address - 接收上传数据的 URI
             *     string method - 所使用的 HTTP 方法(POST 或 GET)
             *     Object userToken - 需要上传的数据流
             
*/


            OpenFileDialog openFileDialog 
=   new  OpenFileDialog()
            {  
// 弹出打开文件对话框要求用户自己选择在本地端打开的图片文件
                Filter  =   " Jpeg Files (*.jpg)|*.jpg|All Files(*.*)|*.* " ,
                Multiselect 
=   false    // 不允许多选 
            };

            
if  (openFileDialog.ShowDialog()  ==   true ) // .DialogResult.OK)
            {
                
// fileinfo = openFileDialog.Files;  // 取得所选择的文件,其中Name为文件名字段,作为绑定字段显示在前端
                fileinfo = openFileDialog.File;

                
if  (fileinfo  !=   null )
                {
                    WebClient webclient 
=   new  WebClient();

                    
string  uploadFileName  =  fileinfo.Name.ToString();  // 获取所选文件的名字

                    
#region  把图片上传到服务器上

                    Uri upTargetUri 
=   new  Uri(String.Format( " http://localhost:51896/WebClientUpLoadStreamHandler.ashx?fileName={0} " , uploadFileName), UriKind.Absolute);  // 指定上传地址

                    webclient.OpenWriteCompleted 
+=   new  OpenWriteCompletedEventHandler(webclient_OpenWriteCompleted);
                    webclient.Headers[
" Content-Type " =   " multipart/form-data " ;

                    webclient.OpenWriteAsync(upTargetUri, 
" POST " , fileinfo.OpenRead());
                    webclient.WriteStreamClosed 
+=   new  WriteStreamClosedEventHandler(webclient_WriteStreamClosed);

                    
#endregion

                }
                
else
                {
                    MessageBox.Show(
" 请选取想要上载的图片!!! " );
                }
            }

        }



        
void  webclient_OpenWriteCompleted( object  sender, OpenWriteCompletedEventArgs e)
        {
            
            
// 将图片数据流发送到服务器上

            
//  e.UserState - 需要上传的流(客户端流)
            Stream clientStream  =  e.UserState  as  Stream;
            
//  e.Result - 目标地址的流(服务端流)
            Stream serverStream  =  e.Result;
            
byte [] buffer  =   new   byte [ 4096 ];
            
int  readcount  =   0 ;
            
//  clientStream.Read - 将需要上传的流读取到指定的字节数组中
             while  ((readcount  =  clientStream.Read(buffer,  0 , buffer.Length))  >   0 )
            {
                
//  serverStream.Write - 将指定的字节数组写入到目标地址的流
                serverStream.Write(buffer,  0 , readcount);
            }
            serverStream.Close();
            clientStream.Close();


        }

        
void  webclient_WriteStreamClosed( object  sender, WriteStreamClosedEventArgs e)
        {
            
// 判断写入是否有异常
             if  (e.Error  !=   null )
            {
                System.Windows.Browser.HtmlPage.Window.Alert(e.Error.Message.ToString());
            }
            
else
            {
                System.Windows.Browser.HtmlPage.Window.Alert(
" 图片上传成功!!! " );
            }
        }
        
#endregion

 Page.xaml.cs全部代码如下:


ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
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.Media.Imaging; //因为要使用BitmapImage
using System.IO;  //因为要使用Stream

namespace SLWebClientStream
ExpandedBlockStart.gifContractedBlock.gif
{
    
public partial class Page : UserControl
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{

        
//1、WebClient 对象一次只能启动一个请求。如果在一个请求完成(包括出错和取消)前,即IsBusy为true时,进行第二个请求,则第二个请求将会抛出 NotSupportedException 类型的异常
        
//2、如果 WebClient 对象的 BaseAddress 属性不为空,则 BaseAddress 与 URI(相对地址) 组合在一起构成绝对 URI
        
//3、WebClient 类的 AllowReadStreamBuffering 属性:是否对从 Internet 资源接收的数据做缓冲处理。默认值为true,将数据缓存在客户端内存中,以便随时被应用程序读取
 


        
//获取选定图片信息
        System.IO.FileInfo fileinfo;


        
public Page()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            InitializeComponent();
        }


ContractedSubBlock.gifExpandedSubBlockStart.gif        
下载图片#region  下载图片
        
private void btnDownload_Click(object sender, RoutedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//向指定的Url发送下载流数据请求 
            String imgUrl = "http://localhost:51896/Bubble.jpg";     
             Uri endpoint 
= new Uri(imgUrl);

            WebClient client 
= new WebClient();
            client.OpenReadCompleted 
+= new OpenReadCompletedEventHandler(OnOpenReadCompleted);
            client.DownloadProgressChanged 
+= new DownloadProgressChangedEventHandler(clientDownloadStream_DownloadProgressChanged);
            client.OpenReadAsync(endpoint);
        }

        
void OnOpenReadCompleted(object sender,OpenReadCompletedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
 
             
//OpenReadCompletedEventArgs.Error - 该异步操作期间是否发生了错误
             
//OpenReadCompletedEventArgs.Cancelled - 该异步操作是否已被取消
             
//OpenReadCompletedEventArgs.Result - 下载后的 Stream 类型的数据
             
//OpenReadCompletedEventArgs.UserState - 用户标识
 
            
if (e.Error != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                MessageBox.Show(e.Error.ToString());
                
return;
            }

            
if (e.Cancelled != true)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
//获取下载的流数据(在此处是图片数据)并显示在图片控件中
                Stream stream = e.Result;
                BitmapImage bitmap 
= new BitmapImage();
                bitmap.SetSource(stream);
                imgDownLoad.Source 
= bitmap;
            }




        }


        
void clientDownloadStream_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//DownloadProgressChangedEventArgs.ProgressPercentage - 下载完成的百分比
            
//DownloadProgressChangedEventArgs.BytesReceived - 当前收到的字节数
            
//DownloadProgressChangedEventArgs.TotalBytesToReceive - 总共需要下载的字节数
            
//DownloadProgressChangedEventArgs.UserState - 用户标识
        
            
this.tbMsgString.Text = string.Format("完成百分比:{0} 当前收到的字节数:{1} 资料大小:{2} ",
              e.ProgressPercentage.ToString() 
+ "%",
              e.BytesReceived.ToString(),
              e.TotalBytesToReceive.ToString());

        }


        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
上传图片#region  上传图片
        
private void btnUpLoad_Click(object sender, RoutedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
/**//*
             *   OpenWriteCompleted - 在打开用于上传的流完成时(包括取消操作及有错误发生时)所触发的事件
             *   WriteStreamClosed - 在写入数据流的异步操作完成时(包括取消操作及有错误发生时)所触发的事件
             *   UploadProgressChanged - 上传数据过程中所触发的事件。如果调用 OpenWriteAsync() 则不会触发此事件
             *   Headers - 与请求相关的的标头的 key/value 对**
             *   OpenWriteAsync(Uri address, string method, Object userToken) - 打开流以使用指定的方法向指定的 URI 写入数据
             *     Uri address - 接收上传数据的 URI
             *     string method - 所使用的 HTTP 方法(POST 或 GET)
             *     Object userToken - 需要上传的数据流
             
*/



            OpenFileDialog openFileDialog 
= new OpenFileDialog()
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{  //弹出打开文件对话框要求用户自己选择在本地端打开的图片文件
                Filter = "Jpeg Files (*.jpg)|*.jpg|All Files(*.*)|*.*",
                Multiselect 
= false  //不允许多选 
            }
;

            
if (openFileDialog.ShowDialog() == true)//.DialogResult.OK)
ExpandedSubBlockStart.gifContractedSubBlock.gif
            {
                
//fileinfo = openFileDialog.Files; //取得所选择的文件,其中Name为文件名字段,作为绑定字段显示在前端
                fileinfo=openFileDialog.File;

                
if (fileinfo != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    WebClient webclient 
= new WebClient();

                    
string uploadFileName = fileinfo.Name.ToString(); //获取所选文件的名字

ContractedSubBlock.gifExpandedSubBlockStart.gif                    
把图片上传到服务器上#region 把图片上传到服务器上

                    Uri upTargetUri 
= new Uri(String.Format("http://localhost:51896/WebClientUpLoadStreamHandler.ashx?fileName={0}", uploadFileName), UriKind.Absolute); //指定上传地址

                    webclient.OpenWriteCompleted 
+= new OpenWriteCompletedEventHandler(webclient_OpenWriteCompleted);
                    webclient.Headers[
"Content-Type"= "multipart/form-data";

                    webclient.OpenWriteAsync(upTargetUri, 
"POST", fileinfo.OpenRead());
                    webclient.WriteStreamClosed 
+= new WriteStreamClosedEventHandler(webclient_WriteStreamClosed);

                    
#endregion


                }

                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    MessageBox.Show(
"请选取想要上载的图片!!!");
                }

            }


        }




        
void webclient_OpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
            
//将图片数据流发送到服务器上

            
// e.UserState - 需要上传的流(客户端流)
            Stream clientStream = e.UserState as Stream;
            
// e.Result - 目标地址的流(服务端流)
            Stream serverStream = e.Result;
            
byte[] buffer = new byte[4096];
            
int readcount = 0;
            
// clientStream.Read - 将需要上传的流读取到指定的字节数组中
            while ((readcount = clientStream.Read(buffer, 0, buffer.Length)) > 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
// serverStream.Write - 将指定的字节数组写入到目标地址的流
                serverStream.Write(buffer, 0, readcount);
            }

            serverStream.Close();
            clientStream.Close();


        }


        
void webclient_WriteStreamClosed(object sender, WriteStreamClosedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//判断写入是否有异常
            if (e.Error != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                System.Windows.Browser.HtmlPage.Window.Alert(e.Error.Message.ToString());
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                System.Windows.Browser.HtmlPage.Window.Alert(
"图片上传成功!!!");
            }

        }

        
#endregion


    }

}

  (二)、服务器端部分
 编写配合上传图片处理的Handler,我们命名为WebClientUpLoadStreamHandler.ashx,代码如下:


using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;

using  System.IO;   // 因为要用到Stream


namespace  SLWebClientStream.Web
{
    
public   class  WebClientUpLoadStreamHandler : IHttpHandler
    {

        
public   void  ProcessRequest(HttpContext context)
        {
            
// 获取上传的数据流
             string  fileNameStr  =  context.Request.QueryString[ " fileName " ];
            Stream sr 
=  context.Request.InputStream;
            
try
            {
                
string  filename  =   "" ;

                filename 
=  fileNameStr;

                
byte [] buffer  =   new   byte [ 4096 ];
                
int  bytesRead  =   0 ;
                
// 将当前数据流写入服务器端文件夹ClientBin下
                 string  targetPath  =  context.Server.MapPath( " Pics/ "   +  filename  +   " .jpg " );
                
using  (FileStream fs  =  File.Create(targetPath,  4096 ))
                {
                    
while  ((bytesRead  =  sr.Read(buffer,  0 , buffer.Length))  >   0 )
                    {
                        
// 向文件中写信息
                        fs.Write(buffer,  0 , bytesRead);
                    }
                }

                context.Response.ContentType 
=   " text/plain " ;
                context.Response.Write(
" 上传成功 " );
            }
            
catch  (Exception e)
            {
                context.Response.ContentType 
=   " text/plain " ;
                context.Response.Write(
" 上传失败, 错误信息: "   +  e.Message);
            }
            
finally
            { sr.Dispose(); }

        }

        
public   bool  IsReusable
        {
            
get
            {
                
return   false ;
            }
        }
    }
}

   完成上述工作后,生成项目,运行后效果如下:
                              

     上传图片后,所上传图处在如下位置
                              


前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值