Silverlight WCF 上传实现

上一篇中提高Silverlight实现文件上传的一些思路,说实在的,在写哪篇文章之前并没有亲身试验过,虽说是思路,但是万一有偏差还是有点冒险。

 

经过自己测试后,得意证明,Silverlight 利用 WCF实现上传确实是如此的简单方便,逻辑上也非常的顺畅。

 

废话不说,看过前一篇文章后对Silverlight 利用 WCF实现上传大概有概念上的理解,下面直接就是代码部分了。

 

此代码只是先了文件上传,界面没怎么做就两个按钮,文件名和上传消息通知都直接显示在按钮上,这是为了让代码看上去简单,更容易理解,见谅。

 

实现:

首先,创建一个ASP.NET项目,然后再该项目中创建一个用于启动于Silverlight的WCF服务 ,也就是一个SVC文件以及.CS代码文件。我取名为Upload.svc,代码如下

 

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.Collections.Generic;

using System.Text;

 

namespace WebApp4SL

{

    [ServiceContract(Namespace = "Zeta")]

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

    public class UpLoad

    {

        [OperationContract]

        public string Upload(byte[] bytes,string filename)

        {

            System.IO.FileStream fs = new System.IO.FileStream(System.Web.HttpContext.Current.Server.MapPath("UploadFile")+"/"+filename,System.IO.FileMode.Create);

 

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

 

            fs.Flush();

 

            fs.Close();

           

            return "成功!";

        }

 

    }

}

 

 

 这里成功与否当然应该加入更多判断,例如文件是否有重名,或者是否是可支持的类型,我的示例中都没有判断,实际项目中都应该加上,还有就是错误处理 TRY。

 

服务器端就此完成,当然,你还得在ASP.NET项目下新建一个目录用于存放上传来的文件,我命名为UploadFile

 

 

接下来就是客户端Silverlight的代码了,首先创建一个Silverlight项目,然后引用刚才我们创建的WCF服务。接下来写Page.xaml及其代码,Page.xaml.cs 如下

 

 

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.Xml;

using System.IO;

using System.Text;

 

namespace SilverlightTest

{

    public partial class Page : UserControl

    {

 

 

        byte[] bytes;

        string filename;

        public Page()

        {

            InitializeComponent();

           

        }

 

        private void UserControl_Loaded(object sender, RoutedEventArgs e)

        {

        }

 

        private void UserControl_KeyDown(object sender, KeyEventArgs e)

        {

        }

 

        private void openfile_Click(object sender, RoutedEventArgs e)

        {

            OpenFileDialog op = new OpenFileDialog();

           

            if (op.ShowDialog()==true)

            {

                FileStream fs = op.File.OpenRead();

 

                bytes = new byte[fs.Length];

 

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

 

                openfile.Content =op.File.Name;

                filename = op.File.Name;

            }

        }

 

        private void upload_Click(object sender, RoutedEventArgs e)

        {

            if (bytes != null)

            {

                WebApp.UpLoadClient uc = new SilverlightTest.WebApp.UpLoadClient();

 

                uc.UploadCompleted += new EventHandler<SilverlightTest.WebApp.UploadCompletedEventArgs>(uc_UploadCompleted);

 

                uc.UploadAsync(bytes,filename);

            }

        }

 

        void uc_UploadCompleted(object sender, SilverlightTest.WebApp.UploadCompletedEventArgs e)

        {

            openfile.Content = e.Result;

        }

    }

}

 

 

很简单,可以说是简陋,但是很能说明问题。

 

最后就是更简单的Page.xaml文件

 

 

<UserControl x:Class="SilverlightTest.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

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

    Width="400" Height="300" xmlns:SilverlightTest="clr-namespace:SilverlightTest" Loaded="UserControl_Loaded" KeyDown="UserControl_KeyDown">

    

     <StackPanel x:Name="sp">

        <Button x:Name="openfile" Content="浏览" Click="openfile_Click"></Button>

        <Button x:Name="upload" Content="上传" Click="upload_Click"></Button>

    </StackPanel>

  

 

</UserControl>

 

至此,完成了Silverlight的上传功能。可以看到,Silverlight在客户端获取文件流,写到了一个缓冲块,然后直接将缓冲块作为WCF服务方法的参数,请求执行WCF服务的方法,这个缓冲块就被传递到了服务器,并在服务器上的WCF服务后台代码被处理,处理效果就是将这个缓冲块写入到一个文件流保存起来。

 

很简单吧,而且很直观,与以往写入到HTTP请求流,再从请求流里操作简单了一些,但是你也许会说,这样的方法并不比ASP.NET里那个上传控件简单多少啊。但是直接用上传控件会遇到的两个问题很让人棘手,第一就是文件的体积问题,上传大体积会消耗很多时间,也占用较大服务器内存,随之而来的就是HTTP超时问题,另一个就是进度问题,HTTP上传是无法显示进度的,当然AJAX的分块可以解决,但是如果我们用SILVERLIGHT,就更简单了,将客户端文件流分块写入到缓冲块,然后再一次次分别去调用WCF的服务方法,保存成分块的小文件,最后,执行一次合并方法,将文件合并后保存,我的这个例里没有实现这个功能,但是改进下很容易,分块后,做进度就不是什么问题了吧,因为有WCF方法的异步回调时间,一切都是那么简单。

 

另外,如果在没有使用分块上传的情况下单个上传文件比较大,或者分块上传单块过大,有可能出现 NOTFOUND异常,为什么,那是你的WCF配置限制引起的,可以在 WEBCONFI文件里进行修改。添加类似以下配置代码

<basicHttpBinding>
<binding name="LargeBuffer" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" textEncoding="UTF-8" sendTimeout="00:05:10" receiveTimeout="00:05:10" openTimeout="00:05:10" closeTimeout="00:05:10">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
</binding>
</basicHttpBinding>

 

如果不知道怎么配置,可以在VS2008里右键点解WEB.CONFIG 选择 编辑WCF配置 进入配置界面。

posted @ 2009-04-26 13:14  ZetaChow晓代码  阅读(743)  评论(0编辑  收藏  举报