锁定老帖子 主题:DWR3 文件上传显示进度条
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-12-13
最后修改:2011-12-22
上传很方便,但是要显示进度条,我没找到相关的接口,我觉得dwr3应该会提供一个方便的接口用来显示进度条,后来研究dwr3的源码,发现在上传文件时,发现有下面的一段代码 if (session != null) { fileUploader.setProgressListener(new SessionProgressListener(session)); session.setAttribute(SessionProgressListener.CANCEL_UPLOAD, null); session.setAttribute(PROGRESS_LISTENER, fileUploader.getProgressListener()); } 这里set了一个进度监听,并且放到session中,于是我就打算不断的从session中获取这个SessionProgressListener,然后使用dwr3推送技术,调用前台的js来改变进度条。 这就是我大概实现的思路,虽然我觉得这样很笨,但是我目前只能这样来获取上次的进度,不知道各位大侠有没有更好的办法。 下面是相关的代码: 1.前台: <%@ page language="java" contentType="text/html; charset=GBK" pageEncoding="GBK"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <%@ include file="/jsp/common/include.jsp"%> <meta http-equiv="Content-Type" content="text/html; charset=GBK"> <title>DWR HELLO</title> <style type="text/css"> .ProgressBar { position: relative; width: 350px; /* 宽度 */ border: 1px solid #B1D632; padding: 1px; text-align:left; } .ProgressBar div { display: block; position: relative; background: #B1D632; color: #333333; height: 20px; /* 高度 */ line-height: 20px; /* 必须和高度一致,文本才能垂直居中 */ text-align:left; } .ProgressBar div span { position: absolute; width: 350px; /* 宽度 */ text-align: center; font-weight: bold; } </style> <script type='text/javascript' src='${contextPath }/dwr/engine.js'> </script> <script type='text/javascript' src='${contextPath }/dwr/util.js'> </script> <script type='text/javascript' src='${contextPath }/dwr/interface/FileUpload.js'> </script> <script type='text/javascript' src='${contextPath }/dwr/interface/UploadListener.js'> </script> <script type='text/javascript' src='${contextPath }/js/dwrjs/dwrHelper.js'> </script> <script type='text/javascript' src='${contextPath }/js/dwrjs/upload.js'> </script> <script type='text/javascript' src='${contextPath }/js/zdialog/zDrag.js'> </script> <script type='text/javascript' src='${contextPath }/js/zdialog/zDialog.js'> </script> <script type="text/javascript"> function addFile(){ if($("#uploadFile").val()==null || $("#uploadFile").val().length <= 0){ return ; } var uploadFile = dwr.util.getValue("uploadFile"); //初始化上传信息 progressBarInit($("#uploadFile").val()); //显示上传进度信息 showDialog(); //DWR3 文件上传 FileUpload.upload(uploadFile, { callback : function(data){ Dialog.close(); $("#file_list").html($("#file_list").html()+"<a href='javascript:void(0);' onclick='downloadFile(\"" + data + "\")'>" + data + "</a><br>"); } }); //开始监听上传数据 0.6秒推送一次 UploadListener.listener(); } /** **只能下载小文件,寻求解决方法 */ function downloadFile(data) { //alert(data); FileUpload.download(data, function(data) { //alert(data); dwr.engine.openInDownload(data); }); } /** **利用弹出插件,显示进度 */ function showDialog(){ var diag = new Dialog(); diag.Width = 400; diag.Height = 300; diag.Title = "上传信息"; diag.InvokeElementId="upload_info" ; diag.ShowCloseButton = false ; //diag.OKEvent = function(){};//点击确定后调用的方法 diag.show(); } </script> </head> <body onload="reverseAjax();"> <p> <input type="file" name="uploadFile" id="uploadFile" /> <input type="button" onclick="addFile()" value="上传" /> </p> <table> <tr><td id="file_list"></td></tr> </table> <table id="upload_info" style="width:400px;text-align:left;display:none;"> <tr> <td width="30%">上传文件名:</td> <td><span id="upload_file_name"> </span></td> </tr> <tr> <td>文件总大小:</td> <td><span id="upload_file_size">0 KB</span></td> </tr> <tr> <td>上传用时:</td> <td><span id="upload_time">0 秒</span></td> </tr> <tr> <td>上传速度:</td> <td><span id="upload_speed">0 KB/s</span></td> </tr> <tr><td id="upload_text" colspan="2">文件上传中,请稍等……</td></tr> <tr> <td colspan="2"> <div class="ProgressBar"> <div id="progress_bar" style="width: 0%;"> <span id="progress_percent">0%</span> </div> </div> </td> </tr> </table> </body> </html> 其中 upload.js 代码如下: /** * @zongb */ var $$ = function (id){return document.getElementById(id)} ; function updateProgress(uploadInfo){ var progressPercent = Math.ceil((uploadInfo.bytesRead / uploadInfo.totalSize) * 100); var secondsElapsed = Math.ceil(uploadInfo.deltaTime/1000); var speed = Math.ceil(uploadInfo.bytesRead / (uploadInfo.deltaTime/1000 * 1024)); //$$('upload_file_name').innerHTML = uploadInfo.curFileName ; $$('upload_file_size').innerHTML =Math.ceil(uploadInfo.totalSize/1024) + ' KB'; $$('upload_time').innerHTML = secondsElapsed + " 秒" ; $$('upload_speed').innerHTML = speed + " KB/s"; $$('progress_bar').style.width = parseInt(progressPercent * 3.5) + 'px'; $$('progress_percent').innerHTML = progressPercent + "%" ; if(progressPercent==100){ $$('upload_text').innerHTML = "处理文件中,请稍后……"; }else{ $$('upload_text').innerHTML = "文件上传中,请稍等……"; } } /** * 初始化上传信息 */ function progressBarInit(uploadFile){ var filename = uploadFile.substring(uploadFile.lastIndexOf("\\")+1,uploadFile.length) ; $$('upload_file_name').innerHTML = filename ; $$('upload_file_size').innerHTML ='0 KB'; $$('upload_time').innerHTML = "0 秒" ; $$('upload_speed').innerHTML = "0 KB/s"; $$('progress_bar').style.width = '0px'; $$('progress_percent').innerHTML = "0%" ; } function reverseAjax() { dwr.engine.setActiveReverseAjax(true); } dwrHelper.js只是一个针对dwr3错误处理 zDrag.js 和 zDialog.js 是用的一个弹出框插件,附件中会列出的 2.然后是dwr3的配置文件(web.xml怎么配置的我就不写了) <create creator="new" javascript="FileUpload"> <param name="class" value="com.method.dwr.Upload"/> </create> <create creator="new" javascript="UploadListener" scope="script"> <param name="class" value="com.method.dwr.TestProgress"/> </create> <convert converter="bean" match="com.method.dwr.util.fileUpload.ProgressInfo"/> 记得在web.xml中加上下面这句,支持推送 <init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value> </init-param> 3.java代码 供前台调用的类 package com.method.dwr; import org.apache.log4j.Logger; import org.directwebremoting.io.FileTransfer; import com.method.dwr.util.exception.ExceptionValidate; import com.method.dwr.util.fileUpload.FileUpload; import com.method.dwr.util.fileUpload.ProgressInfo; public class Upload { public static Logger log = Logger.getLogger(Upload.class) ; private ProgressInfo pi = null; private FileUpload upload = null ; /** * DWR 单文件上传 * 页面编码必须使用GBK,否则上传文件名为中文时,会出现乱码 * @return * @throws Exception */ public String upload(FileTransfer fileTransfer) throws Exception { log.info("=======================") ; upload = new FileUpload(); return upload.upload(fileTransfer,50,"/upload"); } /** * 文件下载 * 在IE下,中文文件名会有乱码出现,待解决。 * @param fileName * @return * @throws Exception */ public FileTransfer download(String fileName) throws Exception{ upload = new FileUpload(); return upload.download(fileName,"/upload"); } } dwr3上传文件的类 package com.method.dwr.util.fileUpload; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import org.apache.log4j.Logger; import org.directwebremoting.WebContext; import org.directwebremoting.WebContextFactory; import org.directwebremoting.io.FileTransfer; import com.method.dwr.util.exception.ExceptionValidate; public class FileUpload { public static Logger log = Logger.getLogger(FileUpload.class) ; private WebContext wctx = null; /** * DWR 单文件上传 * 页面编码必须使用GBK,否则上传文件名为中文时,会出现乱码 * @param fileTransfer * @param maxSizeWithM 允许上传的最大文件 * @param savePath 文件保存的路径(/upload) * @return * @throws Exception */ public String upload(FileTransfer fileTransfer,int maxSizeWithM,String savePath) throws Exception { if(maxSizeWithM != 0 && fileTransfer.getSize() > 1024*1024*maxSizeWithM){ //throw new ExceptionValidate("提示:您上传的单个文件不能超过" + maxSizeWithM + "M !") ; } wctx = WebContextFactory.get(); log.info("----------"+fileTransfer.getSize()) ; //存储的绝对路径 String saveurl = wctx.getHttpServletRequest().getSession() .getServletContext().getRealPath(savePath); log.info("----------" + saveurl) ; String fileName = new String(fileTransfer.getFilename().getBytes(),"GBK"); //文件名 fileName = fileName.substring(fileName.lastIndexOf(java.io.File.separator)+1) ; log.info("-------fileName---" + fileName) ; File file = new File(saveurl + java.io.File.separator + fileName); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } //开始读取文件 byte[] bytes = new byte[1024*10]; FileOutputStream foutput = new FileOutputStream(file); BufferedOutputStream Buff = new BufferedOutputStream(foutput); InputStream fis = fileTransfer.getInputStream(); int len=0; while((len=fis.read(bytes))>0) { Buff.write(bytes,0,len); } Buff.flush(); Buff.close(); foutput.close(); fis.close(); log.info("-----文件上传结束-----") ; return fileName; } /** * 文件下载 * 在IE下,中文文件名会有乱码出现,待解决。 * @param fileName * @return * @throws Exception */ public FileTransfer download(String fileName,String savePath) throws Exception{ wctx = WebContextFactory.get(); // String realtivepath = webContext.getServletContext().getContextPath() // + "/upload/"; log.info("-------fileName-1111--" + fileName) ; String saveurl = wctx.getHttpServletRequest().getSession() .getServletContext().getRealPath(savePath); if (fileName == null || fileName.length() == 0) { fileName = "[BLANK]"; } BufferedInputStream in; try { in = new BufferedInputStream(new FileInputStream(saveurl + java.io.File.separator + fileName)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block throw new ExceptionValidate("您要下载的文件:[" + fileName + "]不存在!"); } ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] temp = new byte[1024*10]; int size = 0; while ((size = in.read(temp)) != -1) { out.write(temp, 0, size); } //log.info(new String(out.toByteArray(),"ISO8859-1")); return new FileTransfer(new String(fileName.getBytes("UTF-8"),"ISO8859-1"),null,out.toByteArray()); } } 这个是存储进度条信息的类 package com.method.dwr.util.fileUpload; import java.util.ArrayList; public class ProgressInfo { private long totalSize = 0; private long bytesRead = 0; private int fileIndex = 0; private long startTime = System.currentTimeMillis(); private long deltaTime = 0; private String uploadedFiles = ""; private boolean isInProgress = true; private boolean isCompleted = false; private String curFileName = ""; private String errorMsg = ""; public String getErrorMsg() { return errorMsg; } public void setErrorMsg(String errorMsg) { this.errorMsg = errorMsg; } public String getCurFileName() { return curFileName; } public void setCurFileName(String curFileName) { this.curFileName = curFileName; } public String getUploadedFiles() { return uploadedFiles; } public void setUploadedFiles(String uploadedFiles) { this.uploadedFiles = uploadedFiles; } public long getStartTime() { return startTime; } public void setStartTime(long startTime) { this.startTime = startTime; } public void setDeltaTime(long deltaTime) { this.deltaTime = deltaTime; } public ProgressInfo() { } public long getTotalSize() { return totalSize; } public void setTotalSize(long totalSize) { this.totalSize = totalSize; } public long getBytesRead() { return bytesRead; } public void setBytesRead(long bytesRead) { this.bytesRead = bytesRead; } public long getDeltaTime() { return System.currentTimeMillis() - this.startTime; } public boolean isInProgress() { return isInProgress; } public int getFileIndex() { return fileIndex; } public void setFileIndex(int fileIndex) { this.fileIndex = fileIndex; } public boolean isCompleted() { return isCompleted; } public void setCompleted(boolean isCompleted) { this.isCompleted = isCompleted; this.isInProgress = false; } public void setInProgress(boolean isInProgress) { this.isInProgress = isInProgress; } } 补充一下代码: package com.method.dwr; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.directwebremoting.ScriptBuffer; import org.directwebremoting.WebContext; import org.directwebremoting.WebContextFactory; import org.directwebremoting.event.SessionProgressListener; import com.method.dwr.util.fileUpload.ProgressInfo; /** * @author 宗波 E-mail:zongb@cntmi.com * @version 创建时间:2011-11-27 下午09:44:14 */ public class TestProgress { public static Logger log = Logger.getLogger(TestProgress.class) ; private static final String PROGRESS_LISTENER = org.directwebremoting.dwrp.CommonsFileUpload.PROGRESS_LISTENER ; /** * 调用前台js的间隔时间,默认为600毫秒 */ private static long SEND_MESSAGE_INTERVAL = 600 ; private ProgressInfo pi = null; private WebContext wctx = null; private SessionProgressListener sp = null ; private HttpSession session = null ; private boolean _stop ; public TestProgress(){ System.out.println("aaaaaaaaaaaaaa") ; } /** * 监听上传文件的进度 * @param interval */ public void listener(long interval){ log.info("==========test=========") ; _stop = false ; wctx = WebContextFactory.get(); session = wctx.getHttpServletRequest().getSession() ; //保存文件的上传信息,用来显示进度条 pi = new ProgressInfo(); ScriptBuffer script = new ScriptBuffer(); script.appendScript("updateProgress(") .appendData(pi) .appendScript(");"); while(!_stop){ sp = (SessionProgressListener)session.getAttribute(PROGRESS_LISTENER) ; log.info("while-------"+getObj(sp)) ; if(sp!=null && sp.getContentLength() > 0){ pi.setTotalSize(sp.getContentLength()) ; pi.setBytesRead(sp.getBytesRead()) ; if(sp.getBytesRead() >= sp.getContentLength()){ log.info("upload finish------------"+getObj(sp)) ; pi.setBytesRead(sp.getContentLength()) ; //停止标识 _stop = true ; //删除session中的记录,否则再次上传文件时开始获取的数据不正确 session.removeAttribute(PROGRESS_LISTENER); } //调用客户端js wctx.getScriptSession().addScript(script); } try { Thread.sleep(interval) ; } catch (InterruptedException e) { e.printStackTrace(); } } pi = null; sp = null ; session = null ; wctx = null; } /** * 开始监听上传文件的进度 */ public void listener(){ listener(SEND_MESSAGE_INTERVAL); } private String getObj(SessionProgressListener sp){ return sp==null?"blank":"{BytesRead=" + sp.getBytesRead() + ";ContentLength=" + sp.getContentLength() +";Item=" + sp.getItem()+"}" ; } public void getDataByclient(){ } } ProgressInfo 传到前台了,在附件中的js使用的。 上面的方法中,有dwr3的下载方法,我的理解是,这个下载方法,是先把文件一次读取到内存中,再在页面中提供下载,这样有个问题:无法下载大文件,不知道各位有没有更好的方法 补充一下,这个进度条的显示,有时候会不太及时,开始怀疑是推送频繁的问题,但是推送频率调大了,还是会出现,不知道什么原因…… 主要想了解下,大家有没有用过后台循环推送、或者 dwr3文件上传显示进度条? 如果大家有什么更好的建议,希望能提出来,大家一起分享 谢谢! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-12-19
难道就没有使用dwr3 上传下载的???
|
|
返回顶楼 | |
发表时间:2011-12-19
UploadListener 没介绍到;
ProgressInfo 没说明调用的地方 最主要的东西都没说, 楼主发贴有意思么 |
|
返回顶楼 | |
发表时间:2011-12-19
kidd3166 写道 UploadListener 没介绍到;
ProgressInfo 没说明调用的地方 最主要的东西都没说, 楼主发贴有意思么 你误会了 楼主这个是 求·助 贴~~ 再就是官方哪里对于dwr的使用和介绍都很少,推送comet中我想找个util类的替换类都没找到资料(util被dwr新版本drop了) 不过话说 少用innerHTML 不是w3c标准的写法 |
|
返回顶楼 | |
发表时间:2011-12-19
dwr这个项目都快夭折了,没想到还有人用
|
|
返回顶楼 | |
发表时间:2011-12-20
,,,,最近在用dwr写客服聊天呢,用要用到他的推技术。
虽然js直接调用java挺方便,不过还感觉是有点麻烦。 你说的这个就不晓得咯。dwr的资料确实很少。官网的介绍,,,,,, |
|
返回顶楼 | |
发表时间:2011-12-20
能不能在客户端判断文件的大小?
|
|
返回顶楼 | |
发表时间:2011-12-20
dafa1892 写道 能不能在客户端判断文件的大小?
沙箱原则是什么? |
|
返回顶楼 | |
发表时间:2011-12-20
我在上个东家做类似web im时有用到dwr,dwr说3会很方便支持推送,不知道现在出正式版没,当时有RC版.
|
|
返回顶楼 | |
发表时间:2011-12-21
如果支持html5的话,可以轻松使用Ajax完成文件的上传,而且Ajax是可以有进度事件的。至于不支持html5的浏览器直接使用Flash也可以。这两种做法都可以在客户端得到进度。
|
|
返回顶楼 | |