最近刚开始学dwr,发现使用起来确实方便多了。现在公司正好有需求要使用文件上传,所以就研究了一下dwr3的文件上传和下载。
上传很方便,但是要显示进度条,我没找到相关的接口,我觉得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"/>
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; } }
上面的方法中,有dwr3的下载方法,我的理解是,这个下载方法,是先把文件一次读取到内存中,再在页面中提供下载,这样有个问题:无法下载大文件,不知道各位有没有更好的方法
如果大家有什么更好的建议,希望能提出来,大家一起分享
谢谢!