本帖最后由 YolandaZheng 于 2009-10-02 07:34:27 编辑

解决方案 »

  1.   

    这个sample http://www.java2000.net/p1457 有很多东西不明白,有人建议用FLASH
      

  2.   

    这个例子我大约看了一下,我给你说一个思路:
    server端要有两个进程配合工作, 一个负责接收上传的字节,我把它叫做UploadController;
    一个负责计算当前进度,我把它叫做ProcessController; 
    还需要一个session范围的变量叫做percentage,当UploadController接收一定数目的字节数之后, 更新一下percentage;
    client端当点击上传的同时运行一个ajax请求(它反复运行直到上传结束),这个请求向ProcessController请求百分比percentage, ProcessController读取session的变量percentage并返回给ajax, 注意Ext.MessageBox有一个方法叫做updateProgress,可以用来更新进度条,ajax请求收到返回的percentage之后, 调用updateProgress就可以了。
      

  3.   

    有几个问题想问下:
    1. 它SERVER 端的代码就是 testUploadFileSaveNOGZIP.jsp 吧?
    2.UploadController在SERVER端怎么体现,是如下代码么:Upload upload = new Upload(request);    
    UploadListener uploadListener = new UploadListener();  
    session.setAttribute("uploadListener",uploadListener);3.一个负责计算当前进度(ProcessController)的,是在 uploadListener 里的么(uploadListener.getTotalCurrent())? 然后在link.jsp里调用取值当前进度?4.ajax请求是 $("SHOW_FRAME").src="link.jsp" 吗?在link.jsp里得到从server传来的uploadListener,然后不断取得当前上传值然后调用Ext.MessageBox.updateProgress(rate,'Uploading...'+current+"/"+total) 更新进度
      

  4.   

    5. $("SHOW_FRAME").src="link.jsp" 我不知道怎么用,一加上去,进度条就出不来了6.session范围的变量percentage在哪?
    倒是session范围的变量uploadListener绑定了upload文件,然后CLIENT断在link.jsp里就可以用uploadListener.getTotalCurrent()得到当前上传量,是么?
      

  5.   

    我一会儿写一个jsp的版本发给你。
      

  6.   

    谢谢你了
    我的上传文件处理是java文件。是一个action 如下:public class UploadFileToTemisAction extends Action { // Log4J logger
    private static Logger logger = Logger
    .getLogger(UploadFileToTemisAction.class);
    public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response) { if (isCancelled(request)) {
    return mapping.findForward("Cancel");
    }

    UploadFileToTemisForm uploadFileToTemisForm = (UploadFileToTemisForm) form;
    FormFile uploadFile = uploadFileToTemisForm.getUploadFile();}}主要是不懂如何监听uploadFile。
    其实它不仅是上传的,上传后的EXCEL里的每一个记录都会存在一个LIST里面,然后用一个循环遍历这个LIST,处理每一个LIST里面的记录,处理完后这个Action 才结束
      

  7.   

    你的意思是不知道uploadFile在当前时刻上传了多少个字节,然后好依照这个字节和总字节数的比例来更新进度条,对吧?
      

  8.   

    是的,但其实这只是第一步,因为整个过程不是仅上传文件的,我用jxl读取EXCEL的每一条数据然后存在一个LIST里面,如下,这个过程很快的。
    InputStream dataInstream = new ByteArrayInputStream(uploadFile
    .getFileData());
    Workbook wb = Workbook.getWorkbook(dataInstream);
    Sheet sheet = wb.getSheet(0);
    List textList = new ArrayList();然后开始调用一个API处理这些数据,这个很耗时了,监听这个过程应该很类似,看看for循环进行了多少就行了吧,但如何不断把这个过程传出去呢,传给client,刷新进度?我不知道用监听可否实现?
      

  9.   

    你直接用struts的file域是没法做上传进度控制的, 因为struts那种做法把上传的过程封装了。
    你可以用commons-fileupload,
      

  10.   

    commons-fileupload 是不是这样我看了一个例子,把原来的
    UploadFileToTemisForm uploadFileToTemisForm = (UploadFileToTemisForm) form; 
    FormFile uploadFile = uploadFileToTemisForm.getUploadFile(); 
    替换成如下,取得表单中的文件:DiskFileItemFactory dfif = new DiskFileItemFactory();  
     dfif.setSizeThreshold(4096);
     ServletFileUpload sfu = new ServletFileUpload(dfif);
     List fileList = null;  
            try {  
                fileList = sfu.parseRequest(request);  
            } catch (FileUploadException e) {}
     Iterator fileItr = fileList.iterator();  
            // 循环处理所有文件  
            FileItem fileUp= null;  
            
            while (fileItr.hasNext()) {  
                FileItem fileItem = null;  
                long size = 0;  
                // 得到当前文件  
                fileItem = (FileItem) fileItr.next();  
        }
    fileItem 就是我上传的文件了,然后我就可以监听过程了?
      

  11.   

    你就用flash做上传吧,FileReference 类,可以监听progerss 事件,progress 事件 (ProgressEvent.PROGRESS):以字节为单位上载文件中的数据时定期调度。
      

  12.   

    实现上传进度条, 用java确实蛮难了, 一般网站都是javascript或者是flash实现了,方便多了, 代码网上一大把!
      

  13.   


    进度条我是用javascript+ext的,后台的数据处理是用JAVA,但是不知道该如何监听上传进度再反馈刷新
      

  14.   

    昨天实在不好意思,感冒没顶住。大体过程是你这样的。只是ServletFileUpload留有一个接口可以直接添加ProgressListener:FileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    //添加监听接口
    upload.setProgressListener(new ProgressListener(){
    public void update(long arg0, long arg1, int arg2) {
    //这里作具体的监听工作
    }
    });
    List items = upload.parseRequest(request);
    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next();
        if (item.isFormField()) {
        
        } else {
            String fieldName = item.getFieldName();
            String fileName = item.getName();
            String contentType = item.getContentType();
            boolean isInMemory = item.isInMemory();
            long sizeInBytes = item.getSize();
            File uploadedFile = new File("c:\\" + System.currentTimeMillis());
            //item.get
            item.write(uploadedFile);
        }
    }
    }
      

  15.   

    你给upload添加ProcessListener之后就不用你干预了。它会自动工作。
    ProcessListener的用法apache.org也有,我贴出来给你看;ProgressListener progressListener = new ProgressListener(){
       public void update(long pBytesRead, long pContentLength, int pItems) {
           System.out.println("We are currently reading item " + pItems);
           if (pContentLength == -1) {
               System.out.println("So far, " + pBytesRead + " bytes have been read.");
           } else {
               System.out.println("So far, " + pBytesRead + " of " + pContentLength
                                  + " bytes have been read.");
           }
       }
    };
    upload.setProgressListener(progressListener);这段代码是把当前拷贝的字节数都打印出来。我们可以变换一下,把当前读取的字节比例算出来,然后set到session:ProgressListener progressListener = new ProgressListener() {
    public void update(long pBytesRead, long pContentLength, int pItems) {
    double percentage = pBytesRead/pContentLength;
    request.getSession().setAttribute("uploadPercentage", percentage);
    }
    };
    upload.setProcessListener(progressListener);放到session后,怎么传输到页面,就按照我7#说的办法。
      

  16.   

    应该是我不好意思啦,真得太谢谢了~
    我明白你的意思了,但是还有两个很关键的问题,能不能再帮我解释下:
    1.我们现在已经把percentage做成session范围的变量了:request.getSession().setAttribute("uploadPercentage", percentage)它会自动更新(对吧?)
    但是如何在client端当点击上传的同时运行一个ajax请求呢?对ajax我是一点对不懂。那个例子上好像不是这样的。
    2.如果现在不是文件upload的百分比,而是FOR循环进行的百分比,如样在FOR循环进行的每一次更新session的变量percentage就行了吧?所以关键是的关键是如何不断用ajax请求这个percentage呢?谢谢,谢谢了
      

  17.   

    sunxing007 希望你还在线啊~~~~
      

  18.   

    processController.jsp<%@ page language="java" import="java.util.*" contentType = "text/html;charset=UTF-8" pageEncoding="utf-8"%>
    <%
    //注意上面的抬头是必须的。否则会有ajax乱码问题。
    //从session取出uploadPercentage并送回浏览器
    Object percent = request.getSession().getAttribute("uploadPercentage");
    String msg = "";
    double d = 0;
    if(percent==null){
    d = 0;
    }
    else{
    d = (Double)percent;
    //System.out.println("+++++++processController: " + d);
    }
    if(d<1){
    //d<0代表正在上传,
    msg = "正在上传文件...";
    out.write("{success:true, msg: '"+msg+"', percentage:'" + d + "', finished: false}");
    }
    else if(d>=1){
    //d>0 代表上传已经结束,开始处理分析excel,
    //本例只是模拟处理excel,在session中放置一个processExcelPercentage,代表分析excel的进度。
    msg = "正在分析处理Excel...";
    String finished = "false";
    double processExcelPercentage = 0.0;
    Object o = request.getSession().getAttribute("processExcelPercentage");
    if(o==null){
    processExcelPercentage = 0.0;
    request.getSession().setAttribute("processExcelPercentage", 0.0);

    }
    else{
    //模拟处理excel,百分比每次递增0.1 
    processExcelPercentage = (Double)o + 0.1;
    request.getSession().setAttribute("processExcelPercentage", processExcelPercentage);
    if(processExcelPercentage>=1){
    //当processExcelPercentage>1代表excel分析完毕。
    request.getSession().removeAttribute("uploadPercentage");
    request.getSession().removeAttribute("processExcelPercentage");
    //客户端判断是否结束的标志
    finished = "true";
    }
    }
    out.write("{success:true, msg: '"+msg+"', percentage:'" + processExcelPercentage + "', finished: "+ finished +"}");
    //注意返回的数据,success代表状态
    //percentage是百分比
    //finished代表整个过程是否结束。
    }
    out.flush();
    %>uploadController.jsp:<%@ page language="java" import="java.util.*, java.io.*, org.apache.commons.fileupload.*, org.apache.commons.fileupload.disk.DiskFileItemFactory, org.apache.commons.fileupload.servlet.ServletFileUpload" pageEncoding="utf-8"%>
    <%
    //注意上面的import的jar包是必须的
    FileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    //因为内部类无法引用request,所以要实现一个。
    class MyProgressListener implements ProgressListener{
    private HttpServletRequest request = null;
    MyProgressListener(HttpServletRequest request){
    this.request = request;
    }
    public void update(long pBytesRead, long pContentLength, int pItems) {
    double percentage = ((double)pBytesRead/(double)pContentLength);
    //上传的进度保存到session,以便processController.jsp使用
    request.getSession().setAttribute("uploadPercentage", percentage);
    }
    }
    upload.setProgressListener(new MyProgressListener(request));
    List items = upload.parseRequest(request);
    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next();
        if (item.isFormField()){
        
        } else {
            //String fieldName = item.getFieldName();
            String fileName = item.getName();
            //String contentType = item.getContentType();
           System.out.println();
            boolean isInMemory = item.isInMemory();
            long sizeInBytes = item.getSize();
            File uploadedFile = new File("c:\\" + System.currentTimeMillis() + fileName.substring(fileName.lastIndexOf(".")));
            item.write(uploadedFile);
        }
    }
    out.write("{success:true,msg:'保存上传文件数据并分析Excel成功!'}");
    out.flush();
    %>upload.html<html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>File Upload Field Example</title>
    <link rel="stylesheet" type="text/css"
    href="ext/resources/css/ext-all.css" />
    <script type="text/javascript" src="ext/adapter/ext/ext-base.js"> </script>
    <script type="text/javascript" src="ext/ext-all.js"> </script>
    <style>
    </style>
    </head>
    <body>
    演示jsp + extjs 显示上传文件进度条并更新进度
    author: <a href="http://blog.csdn.net/sunxing007">http://blog.csdn.net/sunxing007</a>
    <div id="form"></div>
    </body>
    <script>
    var fm = new Ext.FormPanel({
    title: '上传excel文件',
    url:'uploadController.jsp?t=' + new Date(),
    autoScroll:true,
    applyTo: 'form',
    height: 120,
    width: 500,
    frame:false,
    fileUpload: true,
    defaultType:'textfield',
    labelWidth:200,
    items:[{
    xtype:'field',
    fieldLabel:'请选择要上传的Excel文件 ',
    allowBlank:false,
    inputType:'file',
    name:'file'
    }],
    buttons: [{
    text: '开始上传',
    handler: function(){
    //点击'开始上传'之后,将由这个function来处理。
        if(fm.form.isValid()){//验证form, 本例略掉了
        //显示进度条
    Ext.MessageBox.show({ 
        title: '正在上传文件', 
        //msg: 'Processing...', 
        width:240, 
        progress:true, 
        closable:false, 
        buttons:{cancel:'Cancel'} 
    }); 
    //form提交
            fm.getForm().submit();
            //设置一个定时器,每500毫秒向processController发送一次ajax请求
        var timer = setInterval(function(){
         //请求事例
          Ext.Ajax.request({
          //下面的url的写法很关键,我为了这个调试了好半天
          //以后凡是在ajax的请求的url上面都要带上日期戳,
          //否则极有可能每次出现的数据都是一样的,
          //这和浏览器缓存有关
    url: 'processController.jsp?t=' + new Date(),
    method: 'get',
    //处理ajax的返回数据
    success: function(response, options){
    status = response.responseText;
    var obj = Ext.util.JSON.decode(response.responseText);
    if(obj.success!=false){
    if(obj.finished){
    clearInterval(timer);
    //status = response.responseText;
    Ext.MessageBox.updateProgress(1, 'finished', 'finished');
    Ext.MessageBox.hide();
    }
    else{
    Ext.MessageBox.updateProgress(obj.percentage, obj.msg);
    }
    }
    },
    failure: function(){
    clearInterval(timer);
    Ext.Msg.alert('错误', '发生错误了。');

    });
        }, 500);
            
        }
        else{
         Ext.Msg.alert("消息","请先选择Excel文件再上传.");
        }

    }]
    });
    </script>
    </html>
      

  19.   

    以上3个文件拷贝后注意在保存文件的时候一定要注意编码,推荐保存为utf-8;
    你有tomcat么?我是这么测试的,非常方便,
    apache-tomcat-5.5.27\webapps\ROOT 这是一个sample工程,把ext的包拷贝到这里。
    然后把我贴出来的上楼的3个文件也拷贝在这里,然后就可以http://localhost:8080/upload.html测试了。
      

  20.   

    wow~~~
    太谢谢了,我看看先。你可不可以也打个包发给我 [email protected]
      

  21.   

    如果你的ext的目录不是我的jsp里面的样子,要注意更改。我上传了一个100M的文件可以比较清楚的看清上
    传文件的进度和处理excel的进度。
    还有一个问题是,jar包。 建议把apache-commons的jar都拷贝过来到apache-tomcat-5.5.27
    \webapps\ROOT\WEB-INF\lib
    多亏你刷楼了,半天没法出来。
      

  22.   

    发给你了,直接解压在apache-tomcat-5.5.27 \webapps\ROOT
      

  23.   

    顶 sunxing007  收藏了!!!!!!!!
      

  24.   

    东西我总结在http://blog.csdn.net/sunxing007/archive/2009/10/12/4660410.aspx
    欢迎大家下载,使用.
      

  25.   

    欢迎大家下载顶 sunxing007