wodehuajianrui

博客园 首页 新随笔 联系 订阅 管理

近日,我所做的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 = "https://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(
"https://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并加入了三个元素用于对比。运行效果如图所示:

首先我点击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(
"https://files.cnblogs.com/wodehuajianrui/BubblyStyleProject.zip""_self");
        }

 

运行结果如下:

并没有被浏览器拦截,而是正常提示下载。由此可见,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代码中做那些事呢?衷心希望能在方便和安全中间,找到一个万全之策!

 

posted on 2008-07-26 12:20  花间蕊  阅读(901)  评论(1编辑  收藏  举报