zoukankan      html  css  js  c++  java
  • Extjs3 + swfUpload实现多文件上传控件

    要在ExrtJS框架实现选择多文件上传,FileUploadField已经无法满足需求,所以采用了 swfUpload上传控件,上传窗口如下:

    多选文件进行上传(其实是每个文件异步上传),可以中途停止文件上传,移除所选文件等操作。上传窗口代码如下:

    
    
    var ctx = '<%=request.getContextPath()%>';
    Ext.onReady(function(){
        Ext.QuickTips.init();
        new Ext.Window({
            width : 650,
            title : '选择目标文件上传',
            height : 300,
            layout : 'fit',
            items : [
                {
                    xtype:'uploadPanel',
                    border : false,
                    fileSize : 1024*50,//限制文件大小kb
                    uploadUrl : ctx+'/uploadFiles.action',
                    flashUrl : ctx+'/swfupload.swf',//flash文件路径
                    filePostName : 'file', //后台接收参数名称
                    fileTypes : '*.*',//可上传文件类型 *.doc
                    postParams : {savePath:'upload'} //需要传到后台的参数
                }
            ]
        }).show();
    });

    构建完列表后 afterrender 监听函数添加flash生成文件选择窗口:

    keel.UploadPanel.superclass.constructor.call(this,{                
            tbar : [
                {text:'添加文件',iconCls:'add',ref:'../addBtn'},'->',
                {text:'上传',ref:'../uploadBtn',iconCls:'up',handler:this.startUpload,scope:this},'-',
                {text:'停止上传',ref:'../stopBtn',iconCls:'delete',handler:this.stopUpload,scope:this,disabled:true},'-',
                {text:'移除所有',ref:'../deleteBtn',iconCls:'delete2',handler:this.deleteAll,scope:this},'-'
            ],
            layout : 'fit',
            items : [this.gp],
            listeners : {
                'afterrender':function(){
                    var em = this.getTopToolbar().get(0).el.child('em');
                    var placeHolderId = Ext.id();
                    em.setStyle({
                        position : 'relative',
                        display : 'block'
                    });
                    em.createChild({
                        tag : 'div',
                        id : placeHolderId
                    });
                    this.swfupload = new SWFUpload(Ext.apply(this.setting,{
                        button_width : em.getWidth(),
                        button_height : em.getHeight(),
                        button_placeholder_id :placeHolderId
                    }));
                    this.swfupload.uploadStopped = false;
                    Ext.get(this.swfupload.movieName).setStyle({
                        position : 'absolute',
                        top : 0,
                        left : -2//此处需设置为0,否则flash偏右按钮失效
                    });                
                },
                scope : this,
                delay : 100
            }
        });

    后台uploadFiles.action上传成功{"success":true},上传失败返回{"success":false},前台接收进行处理:

    //文件上传成功后触发的事件处理函数 
    onUploadSuccess : function(file, serverData) { var me
    = this.customSettings.scope_handler; var ds = me.gp.store; if (Ext.util.JSON.decode(serverData).success) { for(var i=0;i<ds.getCount();i++){ var rec =ds.getAt(i); if(rec.get('id')==file.id){ rec.set('state', file.filestatus); rec.commit(); } } }else{ for(var i=0;i<ds.getCount();i++){ var rec =ds.getAt(i); if(rec.get('id')==file.id){ rec.set('percent', 0); rec.set('state', -3); rec.commit(); } } } me.linkBtnEvent(); }

    index.jsp 页面代码如下:

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>    
        <title>swfUpload demo</title>
        <link rel="stylesheet" href="<%=request.getContextPath()%>/public/css/common.css" type="text/css" />
        <script type='text/javascript' src="<%=request.getContextPath()%>/public/ext/ext-base.js"></script>
        <script type='text/javascript' src="<%=request.getContextPath()%>/public/ext/ext-all.js"></script>
        <script type="text/javascript" src="<%=request.getContextPath()%>/public/ux/uploader/swfupload.js"></script>
        <script type="text/javascript" src="<%=request.getContextPath()%>/public/ux/uploader/uploaderPanel.js"></script>
      </head>
      
      <body>
      </body>
    </html>

    衷心感谢博主: http://czpae86.iteye.com/blog/834123?page=2#comments

    -------------------------------------------------华丽丽的分割线----------------------------------------------

    满心欢喜的提交了代码,但测试那边同事反馈火狐浏览器无法上传,经过查找网上很多人遇到这种情况,原来是FireFox下使用swfUpload flash上传文件session丢失这个bug。由于项目后台做了登录用户权限控制,点击上传的时候验证未通过请求被抛弃,所以文件上传失败。

    网上技术大拿有如下文章:

    当页面需要使用 session 中的用户信息时,却无法在 Firefox 下使用它进行正常的文件上传。在 IE 下,上传工具能够工作,而一到 Firefox 下,SWFUpload 就会提示错误 302。通过从 Fiddler 抓包,发现上传文件的请求被 302 重定向到了登陆页面,所以无法正常上传文件。也就是说,之前用户登陆后的 session 信息在 Flash 发送的上传请求中丢失了。再一看请求的 header,当中没有可以用来标识当前 session ID 的 cookie 值(对于 J2EE 为 JSESSIONID,PHP 为 PHPSESSID 等)。这是什么原因呢?经过一番搜索,找到了 Adobe 官方的一篇文章,说道:

    A FileReference.upload() currently does not use the same cookies as your browser session if you are using Firefox (on Windows). In such cases, cookie information has to be inserted manually. 

    好吧,这个解释虽然很清楚地表明,Flash 在 Firefox 下进行文件上传不会使用浏览器 cookie 中的 session ID,但是貌似并没有回答文章标题当中的“为什么”,即为什么不使用和浏览器中的 session ID 来进行通信。

    看来 cookie 是指望不上了,那只能像上面说的那样“手工”传递 session ID 了。于是我们可以在 URL 中拼接一个如 ";jsessionid=blahblah" 的字符串(注意要拼在路径之后,参数之前),像下面这样:

    uploadUrl : 'http://example.com/app;jsessionid=blahblah'

    Servlet 规范 7.1.3 节中的规定,当客户端不接受 cookie 时,Servlet 容器应当能解析出这类 URL 中的 JSESSIONID,来维持当前 session 的状态。其他服务器端环境中也有类似的机制。于是我们对文件上传功能做了一定的修改:在用户进入上传页面时,就把当前的 session ID 写到页面中,作为 JavaScript 变量拼接到 SWFUpload 上传文件的目标 URL 中,Flash 就可以利用我们人工传入的 JSESSIONID 来维持登陆状态了。当开始上传时,Flash 通过自己的连接通道向服务器发送数据,但是因为请求的路径中包含了 session 信息所以可以和浏览器的 session 状态保持同步,服务器可以通过 URL 中的 session ID 来获取用户登录的信息。

    于是,302 错误被解决了,看起来一切都 OK 了。可是,不久我们又发现了新的问题:当用户打开上传页面后较长时间没有操作,服务器端的 session 超时了,这个时候进行文件的上传用的还是超时的那个 session ID,所以会失败也是应该的。但是当这个时候用户重新进行了登录,再次进入上传页面上传,却仍然会失败,只有重新启动浏览器才能再次进行上传。这是为什么 呢?从服务器端错误来看,还是用户的登陆信息丢失的问题,也就是说,Flash 在上传文件时,还是没能将用户进行过登陆的这个 session ID 成功传递给服务器端。通过在 Fiddler 中抓包分析,终于找到了原因。

    文章来源 http://lync.in/session-trap-on-uploading-files-using-flash-in-firefox/

    这个方法可以解决大部分网友遇到seesion丢失的问题,但我的项目里调用的是jsf的统一登录接口,没有得到产生的一级域名cookie,按照这种解决方式上传请求还是会被抛弃,焦头烂额的搞了几个小时,突然想到让上传的方法不被Interceptor拦截不就解决了吗,山重水复疑无路,最后在拦截器配置文件里修改一下:

    exclude.path=/common/uploadFiles.do,/common/uploadImgs.do

    经过这样的一个过程基本上实现了多文件上传的功能,适用于后台上传文件的代码没有用到seesion这情况。

  • 相关阅读:
    剑指Offer-11.二进制中1的个数(C++/Java)
    剑指Offer-10.矩形覆盖(C++/Java)
    剑指Offer-9.变态跳台阶(C++/Java)
    UVA 1608 Non-boring sequence 不无聊的序列(分治,中途相遇)
    UVA1607 Gates 与非门电路 (二分)
    UVA 1451 Average平均值 (数形结合,斜率优化)
    UVA 1471 Defense Lines 防线 (LIS变形)
    UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
    UVA 11134 FabledRooks 传说中的车 (问题分解)
    UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)
  • 原文地址:https://www.cnblogs.com/yzuzhang/p/5127345.html
Copyright © 2011-2022 走看看