`
conkeyn
  • 浏览: 1505026 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

利用dwr跨域上传文件的实现

阅读更多

最近产品中需要在一个域下,上传文件到另外一个域,并且显示上传文件的进度。

发现了一个国外的哥们写的上传显示进度的程序,还挺好使,您别说,还针对得起咱这张脸。但是这个程序是在一个服务上运行的,所以需要改造一下。

这个程序采用的是dwr的方式返回上传文件的信息,所以改造的第一步就是要配置dwr跨域访问。

比如在A域上传文件到B域,下面是设置的步骤:

1,配置B服务器的web.xml文件,使其上面的dwr可以被A域调用

   
    <servlet>
        <servlet-name>dwr-invoker</servlet-name>
        <display-name>DWR Servlet</display-name>
        <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <!--<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>-->
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>logLevel</param-name>
            <param-value>WARN</param-value>
        </init-param>
        <init-param>
            <param-name>allowGetForSafariButMakeForgeryEasier</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>crossDomainSessionSecurity</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>allowScriptTagRemoting</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

在dwr配置文件中配置:

        <create creator="new" javascript="UploadMonitor">
            <param name="class" value="com.xxx.xxx.xxx.upload.UploadMonitor"/>
        </create>

原来的demo程序中定义了convert

<convert converter="bean" match="com.xxx.xxx.xxx.upload.UploadInfo"/>

但 是经过测试,跨域调用的情况下,A域的js代码不能识别UploadInfo类.于是把B域中的UploadMonitor中的方法改了,不再返回 UploadInfo类型的对象,而返回UploadInfo的JSON字符串形式。在A域中的js中解析该JSON字符串,得多uploadInfo对 象。

2, 配置A域的DWR.xml

    <create creator="new" javascript="UploadMonitor">           
    </create>

在A中的页面中引入

<script type='text/javascript' src='http://58.30.18.128/dwr/interface/UploadMonitor.js'></script>

这样就可以在js中引入UploadMonitor对象

在使用UploadMonitor对象的时候需要设置_path等属性

    DWREngine.setMethod(dwr.engine.ScriptTag); //设置可以跨域访问
    UploadMonitor._path = "http://58.30.128./dwr/ "; //跨域路径
    UploadMonitor.getUploadInfo(updateProgress);

    ……

解析JSON对象:

var uploadInfo = eval("(" + jsonExpression + ")");

下面可以直接使用uploadInfo对象。

3,因为需要监测上传的进度信息,所以需要每秒调用一次B域的UploadMonitor的方法,获得上传进度。UploadMonitor实现的方式是从session中获取进度信息,session中的进度信息是被listener实时更新的。

在这个地方出了一个问题:浏览器默认是禁用第三方cookie的,所以B域无法向客户端写入cookie,导致每次请求UploadMonitor都从新分配一个session,以至于无从获取进度信息。

解决方式是在 B域中需要跨域操作的页面或者dwr类中添加下面的代码:

response.addHeader("P3P","CP=CAO PSA OUR");

详细信息可以参考 p3p协议的说明。

基本上解决了跨域问题,但是还有一个小bug,跨域请求的时候,第一次请求获得的session不是最终的session,可以打印出sessionId观察一下。 所以每次点击上传文件,第一次都失败,第二次才可以。问了别人,他们也存在这种问题。

所以我的解决方法是:A域的页面中设置一个隐藏的IFRAME,src为B域的一个任意jsp,当打开A页面的时候,隐藏地先调用一下这个jsp,目的是为了规避第一次session无效的情况。

这样,当点击上传文件的时候,就正常了,其实这个时候获得是B域第二次请求的session,这个session是正常的,不会丢失。

参考:   

p3p解决跨域cookie:

http://hi.baidu.com/yxzhklotus/blog/item/048531735829681d8601b00c.html    
http://flyfog.spaces.live.com/blog/cns!6E55C79CCBF7C220!566.entry  

dwr跨域:

http://www.blogjava.net/josson/archive/2008/01/02/169941.html         

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics