My Silverlight系列(4)——恼人的Silverlight文件操作

近日,我所做的Silverlight项目有这么一个需求:点击一个控件,就像在HTML上点击一个超链接一样,由浏览器提示下载某一个文件,当然文件的Uri是已知,是通过这次点击触发的事件处理程序计算得到的。

 

为了实现这个目的,我试验了很多的方法,由于Silverlight只支持隔离存储区,而且它没有类似于超链接的控件,因此我必须求助于js和asp.net。在我转载的一篇文章里,那种手段的确让人眼前一亮,但是试验的结果却令我很不满意。在这里我模拟一下那种实现方法,并且给出结果。

 

Silverlight cs文件中代码如下:

 

         private   void  Button_Click( object  sender, RoutedEventArgs e)
        
{
            
string uri_Site = "http://www.cnblogs.com";
            
string uri_File = "http://files.cnblogs.com/wodehuajianrui/BubblyStyleProject.zip";
            Object[] args 
= {uri_Site,uri_File};
            HtmlPage.Window.Invoke(
"silverlightbutton_onclick", args);
            HtmlPage.Window.Invoke(
"setLinkHref", args);
        }

aspx中的HTML代码如下:

 

div style="margin-bottom:100px">
   
< id ="download"  href =""  target ="_blank"  style =" margin-right:58px" > Download a File </ a >
   
< id ="open"  href =""  target ="_blank"  style =" margin-right:65px" > Open a Site </ a >
   
< input  id ="button"  type ="button"  value ="Download"  onclick ="return Button_onclick()"   />
</ div >

 

aspx中js代码如下:

 

    <script language="javascript" type="text/javascript">
    
        
function Button_onclick() {

              window.open("http://www.cnblogs.com","_blank");
            window.open(
"http://files.cnblogs.com/wodehuajianrui/BubblyStyleProject.zip""_blank");
        }


        
function silverlightbutton_onclick() {
            
if (arguments.length > 0{
                window.open(arguments[
0], "_blank");
                window.open(arguments[
1], "_blank");
            }

        }


        
function setLinkHref() {
            
if (arguments.length > 0{
                open.href 
= arguments[0];
                download.href 
= arguments[1];                
            }

        }


    
</script>

 

解释一下这些代码的作用:首先,在sliverlight的xaml文件中我定义了一个button,它的事件处理代码如第一段所示,然后我在aspx页面中加入了一个div并加入了三个元素用于对比。运行效果如图所示:

My Silverlight系列(4)——恼人的Silverlight文件操作

首先我点击silverlight中的button,结果是打开两个页面,一个为博客园首页,另一个是指向一个file的链接,博客园首页成功打开并停留,另一个窗口自动关闭。

然后我点击aspx中的button,结果是打开两个页面,一个为博客园首页,另一个是指向一个file的链接,博客园首页成功打开并停留,另一个窗口提示文件下载。

由于点击silverlight的button同时为两个链接赋值,那两个链接也可以正常打开,指向文件的链接提示下载。

 

现在的问题就是,用silverlight调用js方法,这种打开文件链接的操作,会自动取消掉。即使我不从silverlight传递参数而直接调用js中的Button_click方法,结果是一样的,打开文件的新窗口会自动关闭,并不提示下载。

 

有意思的是,如果我们把代码稍作改动,将silverlight调用的js方法改为:

         function  silverlightbutton_onclick()  {
            
if (arguments.length > 0{
                window.open(arguments[
0], "_blank");
                window.open(arguments[
1], "_self");
            }

        }

 

让那个文件在本窗口打开,事情就变得不一样了。如图所示:

在我允许下载之后,页面刷新,如果我再点击silverlight的button,文件下载的提示正常显示。相应的,我把aspx中button的响应代码也做修改:

 

         function  Button_onclick()  {
            window.open(
"http://files.cnblogs.com/wodehuajianrui/BubblyStyleProject.zip""_self");
        }

 

运行结果如下:

My Silverlight系列(4)——恼人的Silverlight文件操作

并没有被浏览器拦截,而是正常提示下载。由此可见,sliverlight出于安全因素的考虑,极大地限制了它的行为。同时,这是我调用js的结果,如果我调用dom,让aspx页面向我的浏览器post一个文件,也会被拦截……本来我们用sliverlight是为了提高用户体验,但是这样页面频繁的刷新,而且还总跳出提示,让人非常的不爽。。。

 

我想投机取巧的方法也不是没有,微软在他的MSN space中的SkyDrive中,做了一些手脚,他的是一个aspx页,但是如果是通过Server主动将文件post过来的话,一定会被浏览器拦截的,所以微软的工程师想了一个办法,他们巧妙的应用CSS,将一个链接打扮得像一个button,连on:focus伪类都用上了,然后动态的利用js为链接的href赋值,从而当用户点击那个长得像button的链接的时候,就会直接下载文件(因为这是用户自己的get请求,所以浏览器不会拦截)。所以在silverlight上我们完全也可以使用类似的办法欺骗用户。。。。

 

说到这,我希望微软在开发下一个版本的silverlight时,考虑将这些限制解除,这样那样的限制实在太讨厌了,silverlight既然可以通过js来做一些事,我们何不让它就在托管的.net代码中做那些事呢?衷心希望能在方便和安全中间,找到一个万全之策!

 

你可能感兴趣的:(silverlight)