您的位置:首页 > 编程语言 > Java开发

Java DWR Extjs Servlet 文件上传 进度条

2013-10-11 23:48 567 查看
上一篇博文里面详细介绍了Java Servlet 文件上传,这篇博文将为文件上传添加进度条,其中会利用DWR和Extjs。

1、项目的结构图



(1)要导入相应的JAR包和EXTJS文件。

(2)FileProgressListener

package com.fileupload;

import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.ProgressListener;
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContext;
import org.directwebremoting.ServerContextFactory;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory.WebContextBuilder;
import org.directwebremoting.impl.DefaultWebContextBuilder;

public class FileProgressListener implements ProgressListener {
private long last_percentage = 0;
private long percentage = 0;
private HttpServletRequest request;
private HttpServletResponse response;

public FileProgressListener(HttpServletRequest request, HttpServletResponse response){
this.request = request;
this.response = response;
}

public void update(long pBytesRead, long pContentLength, int pItems) {
percentage = (pBytesRead * 100) / pContentLength;
if(percentage > 0 && percentage % 5 == 0 && percentage > last_percentage){
last_percentage = percentage;
System.out.println("已完成"+percentage+"%,文件大小是:"+pContentLength);
updateProgress(percentage);
}
}

/**
* 向页面index.jsp推送文件上传完成的百分比,推送到方法refreshProgress中。
* @param percentage
*/
public void updateProgress(long percentage){
ScriptBuffer scriptBuffer = new ScriptBuffer();
scriptBuffer.appendScript("try{");
scriptBuffer.appendScript("if(refreshProgress){");
scriptBuffer.appendScript("refreshProgress");
scriptBuffer.appendScript("(");
scriptBuffer.appendData(percentage);
scriptBuffer.appendScript(")}");
scriptBuffer.appendScript("} catch(e){alert(e)}");

ServerContext sc = ServerContextFactory.get();
WebContextBuilder webBuilder = new DefaultWebContextBuilder();
webBuilder.engageThread(sc.getContainer(), request, response);
WebContext webContext = webBuilder.get();
if(webContext == null){
return;
}

Collection<ScriptSession> sessions = webContext.getScriptSessionsByPage("/FileUpload/index.jsp");
if (sessions == null || sessions.isEmpty()) {
return;
}

for (ScriptSession scriptSession : sessions) {
if (scriptSession != null) {
scriptSession.addScript(scriptBuffer);
}
}
}

public void setPercentage(long percentage) {
this.percentage = percentage;
}

public long getPercentage() {
return percentage;
}

}

(3)UpLoadServlet

package com.fileupload;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UpLoadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//上传文件最大为100M
private static final int FILE_MAX_SIZE = 100 * 1024 * 1024;
//设定阀值1M,如果超过这个值,则文件就直接写到临时文件,不会一直占用内存
//利用这个特性可在上传大文件的时候不会占用大量内存,可以提高并发使用量。
private static final int THRESHOLD_SIZE = 1024 * 1024;

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
DiskFileItemFactory df = new DiskFileItemFactory();
df.setSizeThreshold(THRESHOLD_SIZE);
String result = "";
try {
File f = new File("E:\\temp");
if (!f.exists()) {
f.mkdirs();
}

df.setRepository(f);
ServletFileUpload sf = new ServletFileUpload(df);
sf.setFileSizeMax(FILE_MAX_SIZE);

FileProgressListener fileProgressListener = new FileProgressListener(request, response);
sf.setProgressListener(fileProgressListener);
List list = null;
try {
list = sf.parseRequest(request);
} catch (Exception e) {
e.printStackTrace();
result = "上传失败:"+e.getMessage();
}

if(list != null && !list.isEmpty()){
for (int i = 0; i < list.size(); i++) {
FileItem fileItem = (FileItem) list.get(i);
String fileName = fileItem.getName();
if(fileName == null || "".equals(fileName.trim())){
continue;
}

File ff = new File("E:\\files");
if (!ff.exists()) {
ff.mkdirs();
}

File f2 = new File(ff, fileName);
fileItem.write(f2);
result = "上传成功";
}
}
} catch (Exception e) {
e.printStackTrace();
result = "上传失败:"+e.getMessage();
}

response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.println("<script>");
out.println("alert('"+result+"');");
out.println("</script>");
out.flush();
out.close();
}

}

(4)log4j.properties

这个是日志配置文件,用来打印系统日志的。

#stdout
log4j.rootLogger=INFO ,stdout

#Console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold =INFO
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p %c{1}:%L - %m%n

(5)dwr.xml

这是DWR的配置文件,用于配置BEAN其他业务类,暂时没用到,所以就没配置什么东西,本文使用DWR主要是使用它的推送功能,来动态更新进度条。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
<dwr>
<allow>
</allow>
</dwr>

(6)web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.fileupload.UpLoadServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Upload</servlet-name>
<url-pattern>/dwr/fileupload</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</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>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>pollAndCometEnabled</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>initApplicationScopeCreatorsAtStartup</param-name>
<param-value>true</param-value>
</init-param>
<!-- polling方式:在comet方式的基础之上,再配置以下参数 -->
<init-param>
<param-name>org.directwebremoting.extend.ServerLoadMonitor</param-name>
<param-value>org.directwebremoting.impl.PollingServerLoadMonitor</param-value>
</init-param>
<!-- 毫秒数。页面默认的请求间隔时间是5秒 -->
<init-param>
<param-name>disconnectedTime</param-name>
<param-value>100</param-value>
</init-param>
<init-param>
<param-name>maxWaitAfterWrite</param-name>
<param-value>500</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>

(7)index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>文件上传-进度条</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/ext-3.2.1.1/resources/css/ext-all.css" />
<script type="text/javascript" src="${pageContext.request.contextPath}/ext-3.2.1.1/adapter/ext/ext-base-debug.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/ext-3.2.1.1/ext-all.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/ext-3.2.1.1/ext-lang-zh_CN.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>

<script type="text/javascript">
dwr.engine.setActiveReverseAjax(true);//开启DWR的推送功能
</script>

<script type="text/javascript" language="javascript">

<script type="text/javascript">
Ext.onReady(function(){
var formPanel = new Ext.FormPanel({
renderTo: Ext.getBody(),
title: '上传文件',
fileUpload:true,
items:[ {
xtype: 'textfield',
id: 'file',
fieldLabel: '选择文件',
inputType: 'file',
buttonText: '浏览',
width: 258
},
{
text: "上传",
xtype: "button",
handler:function(){
var file = Ext.getCmp("file");
if(file.getValue() == ''){
Ext.MessageBox.alert('提示', '请选择文件!');
return;
}

var win = new Ext.Window({
title: "进度条",
autoScroll: true,
width: Ext.lib.Dom.getViewWidth() > 650 ? 650 : Ext.lib.Dom.getViewWidth() - 100,
autoHeight: true,
closable: true,
layout: 'fit',
items: [
new Ext.ProgressBar({
id: 'progresBar',
anchor: '100%',
listeners: {
afterrender: function(b) {
b.progressBar.setHeight(18);
}
}
})
]
});

win.show();
formPanel.form.submit({
url: 'dwr/fileupload',
method: "POST",
success: function(form, action) {
alert("success");
win.close();
},
failure:function(form,action){
alert("failure");
win.close();
}
});
}
}]
});
});
function refreshProgress(percentage) {
Ext.getCmp('progresBar').updateProgress(parseFloat(percentage)/100,
'已完成' + parseInt(percentage) + '%', true);
}
</script>
</head>
<body>
</body>
</html>

2、系统运行结果

(1)上传页面



(2)文件上传中



(3)文件上传完成



3、总结

本文使用DWR+EXTJS+Servlet+commons_fileupload基本实现了上传文件的功能,并且附带进度条,但也有一些缺陷。

3.1、没有判断文件的大小

如果文件超过限制则会上传失败(需要上传超过大小限制后才抛出异常),没有在页面上或Servlet中做判断。

要获取文件的大小有两种:

(1)、修改浏览器的安全配置,通过ActiveXObject获取。

但这会影响影响浏览器的安全性。

<script type="text/javascript" language="javascript">
//获取文件大小
function getFileSize(fileName)
{
if(document.all)
{
var fso = new ActiveXObject('Scripting.FileSystemObject');
var file = fso.GetFile(fileName);
var size = file.Size;
var size_str = "";
if(size > 1024*1024*1024){
size_str=size/(1024*1024*1024)+"G";
}else if(size > 1024*1024){
size_str=size/(1024*1024)+"M";
}else if(size > 1024){
size_str=size/(1024)+"K";
}else{
size_str=size + "B";
}
return size_str;
}
}
</script>

(2)、利用FLASH获取。

这是网上的说法,以后再慢慢摸索。

3.2 不支持上传大文件

如果文件的大小超过500M,则很可能上传失败。

3.3 不支持断点续传

如果上传的过程中出现问题导致中断,再次上传时并不支持断点续传。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: